学习C++类,首先要说C中的结构体,虽然C++类扩展了C中的结构体,可以添加成员函数,但他们是有区别的。在结构体中,成员变量、成员函数都是公有的,而类中,一般是成员变量是私有的,成员函数是公有的,私有的成员变量一般对象不可调用(数据隐藏),只能是成员函数来调用。

代码1:

 #include <iostream>
using namespace std; class MyClass
{
private:
int m_value;
public:
int get();
void set(int n);
}; int MyClass::get()
{
return m_value;
} void MyClass::set(int n)
{
m_value=n;
} int main()
{
MyClass myclass;
//cout<<myclass.m_value<<endl;
cout<<myclass.get()<<endl; myclass.set();
cout<<myclass.get()<<endl;
return ;
}

如果没有注释掉26行,编译时会出现error C2248: 'm_value' : cannot access private member declared in class 'MyClass',即应证了类中的私有成员变量只能通过公有成员函数调用,对象是不能直接获取的。

执行27行后,显示的是一个不确定的负数,其实,执行25行的MyClass myclass;后编译系统为对象myclass的数据成员(m_value)分配内存空间,并调用默认构造函数MyClass( )自动地初始化对象myclass的m_value值设置为一不确定的值。当然,我们也可以自己设计构造函数。

构造函数主要可以分为如下几种形式:

无参数构造函数 如果创建一个类你没有写任何构造函数,则系统会自动生成默认的无参构造函数,函数为空,什么都不做。只要你写了一个下面的某一种构造函数,系统就不会再自动生成这样一个默认的构造函数,如果希望有一个这样的无参构造函数,则需要自己显示地写出来;

一般构造函数(也称重载构造函数) 一般构造函数可以有各种参数形式,一个类可以有多个一般构造函数,前提是参数的个数或者类型不同(基于c++的重载函数原理)。 创建对象时根据传入的参数不同调用不同的构造函数;

复制构造函数(也称为拷贝构造函数) 复制构造函数参数为类对象本身的引用,用于根据一个已存在的对象复制出一个新的该类的对象,一般在函数中会将已存在对象的数据成员的值复制一份到新创建的对象中.若没有显示的写复制构造函数,则系统会默认创建一个复制构造函数,但当类中有指针成员时,由系统默认创建该复制构造函数会存在风险,具体原因请查询 有关 “浅拷贝” 、“深拷贝”的文章论述.

代码2

 #include <iostream>
using namespace std; class MyClass
{
private:
int m_value;
public:
MyClass(){m_value=;} //无参构造函数
MyClass(int n){m_value=n;} //一般构造函数
MyClass(const MyClass &my){m_value=my.m_value;} //复制构造函数
int get();
void set(int n); }; int MyClass::get()
{
return m_value;
} void MyClass::set(int n)
{
m_value=n;
} int main()
{
MyClass myclass1;
cout<<myclass1.get()<<endl; MyClass myclass2();
//MyClass myclass2=MyClass(4);
cout<<myclass2.get()<<endl; MyClass myclass;
MyClass myclass3(myclass);
cout<<myclass3.get()<<endl; return ;
}

代码2分别定义了无参构造函数、一般构造函数和复制构造函数。在主函数中,29行调用了无参构造函数,32行调用了一般构造函数,且它的作用等价注释掉的33行,37行调用了复制构造函数,即通过对象myclass来创建对象myclass3。

其实对于无参构造函数、一般构造函数还有另一种形式:

queue(int qs):qsize(qs),items(0),front(NULL),rear(NULL){}

即由冒号和逗号分隔的初始化列表,被放在构造函数参数的右括号后,函数体的左括号之前。

代码3

 #include <iostream>
using namespace std; class MyClass
{
private:
int m_value;
public:
MyClass(int n){m_value=n;}
int get();
void set(int n);
void show();
}; int MyClass::get()
{
return m_value;
} void MyClass::set(int n)
{
m_value=n;
} void MyClass::show()
{
cout<<m_value<<endl;
} int main()
{
MyClass myclass1();
myclass1.show(); MyClass myclass2=myclass1;
myclass2.show(); return ;
}

在代码3中,32行调用自定义的构造函数创建对象myclass1,而35行,却是调用的系统默认的复制构造函数,即系统为对象myclass2 分配了内存并完成了与对象myclass1 的复制过程.编译系统的机制是,如果系统类没有自己定义复制构造函数,会采用默认的,如果自己定义了,则会用定义的,其实代码3和代码4(自定义)的作用和效果是相同的。

代码4

 #include <iostream>
using namespace std; class MyClass
{
private:
int m_value;
public:
MyClass(int n){m_value=n;}
MyClass(const MyClass &my){m_value=my.m_value;}
int get();
void set(int n);
void show();
}; int MyClass::get()
{
return m_value;
} void MyClass::set(int n)
{
m_value=n;
} void MyClass::show()
{
cout<<m_value<<endl;
} int main()
{
MyClass myclass1();
myclass1.show(); MyClass myclass2=myclass1;
myclass2.show(); return ;
}

代码4中10行就是我们自定义的复制构造函数,复制构造函数是一种特殊的构造函数,函数的名称必须和类名称一致,它必须的一个参数是本类型的一个引用变量,且没有其他参数或其他参数都有默认值。

复制构造函数用于将一个对象复制到新创建的对象中,也就是说,它用于初始化过程中(包括按值传递参数),而不是常规的赋值过程中。
那么什么时候需要一般的构造函数,什么时候需要复制构造函数:总的来说,以下三种情况需要复制构造函数,具体

1. 对象以值传递的方式传入函数参数

2. 对象以值传递的方式从函数返回

3. 对象需要通过另外一个对象进行初始化

其实以上代码中的复制构造函数就是所谓的浅拷贝,即只对对象中的数据成员进行简单的赋值,默认拷贝构造函数执行的也是浅拷贝。大多情况下“浅拷贝”已经能很好地工作了,但是一旦对象存在了动态成员或静态成员,那么浅拷贝就会出问题。

再次学习C++类之构造函数的更多相关文章

  1. 再次学习 java 类的编译

    做JAVA开发的都知道myeclipse, 我们在myeclipse中新建一个类,然后保存, 如何正常的话,那么在项目指定的目录(也就是项目的output目录)就会生成同名的class文件, 可是,我 ...

  2. 【C++学习之路】派生类的构造函数(一)

    一.简单派生类的构造函数 1.所谓简单派生类,就是指派生类中不包含基类的内嵌对象的派生类. 2.一般来说,这样的派生类的构造函数的形式是: student( int i, string nam, in ...

  3. C++学习17派生类的构造函数

    基类的构造函数不能被继承,在声明派生类时,对继承过来的成员变量的初始化工作也要由派生类的构造函数来完成.所以在设计派生类的构造函数时,不仅要考虑派生类新增的成员变量,还要考虑基类的成员变量,要让它们都 ...

  4. 【C++学习之路】组合类的构造函数

    1 #include <iostream> using namespace std; class A { public: A(){ cout << "调用A无参&qu ...

  5. 【C++学习之路】派生类的构造函数(三)

    三.多层继承的派生类 1.多层继承的派生类只需在构造函数的初始化列表中写出直接基类的构造函数即可 class student { public: student(int n, string nam) ...

  6. 【C++学习之路】派生类的构造函数(二)

    二.有内嵌对象的派生类 1.一般来说,我们会这样定义构造函数 student( int i, string nam, int pid, string pnam, int sid) : person( ...

  7. C++学习之路—继承与派生(二):派生类的构造函数与析构函数

    (根据<C++程序设计>(谭浩强)整理,整理者:华科小涛,@http://www.cnblogs.com/hust-ghtao转载请注明) 由于基类的构造函数和析构函数是不能被继承的,所以 ...

  8. C++学习笔记(6)----基类和派生类的构造函数和析构函数的执行顺序

    基类和派生类:构造函数和析构函数的执行顺序 在Visual Studio中,新建控制台工程,构造类如下: #include<iostream> using namespace std; c ...

  9. c++学习笔记4,派生类的构造函数与析构函数的调用顺序(一)

    測试源代码: //測试派生类的构造函数的调用顺序何时调用 //Fedora20 gcc version=4.8.2 #include <iostream> using namespace ...

随机推荐

  1. Java中的文件操作

    在使用计算机编程中,常常会用到对于文件的操作,以下是我对于Java中文件的相关内容学习之后的一个总结和在学习过程中遇到的一些问题. 一.什么是文件 对于文件进行操作,首先我们要知道什么是文件.在此之前 ...

  2. iOS之原生地图与高德地图

    原生地图 1.什么是LBS LBS: 基于位置的服务 Location Based Service 实际应用:大众点评,陌陌,微信,美团等需要用到地图或定位的App 2.定位方式 1.GPS定位 2. ...

  3. linux 安装GCC

    研究生阶段已经开始了一段时间了,选了LINUX深入分析,之前没怎么接触过,感觉还是有点难度的.不,好像是很难. 从学校借了一台电脑,安装了UBUNTU12.04的系统,可是不知道怎么地,这个系统里,没 ...

  4. Adobe Edge Animate –解决图形边缘精确检测问题-通过jquery加载svg图片

    Adobe Edge Animate –解决图形边缘精确检测问题-通过jquery加载svg图片 版权声明: 本文版权属于 北京联友天下科技发展有限公司. 转载的时候请注明版权和原文地址. 在edge ...

  5. LeetCode 345

    Reverse Vowels of a String Write a function that takes a string as input and reverse only the vowels ...

  6. hdu 3093 动态规划

    思路:直接引用论文的话. 暂时先不考虑“使剩下的物品都放不下”的条件,那就是求 0-1 背包的所有可行方案. 用 Fi[j]表示前 i 件物品中选若干件总体积为 j 的方案数,初始为 F0[0]=1, ...

  7. EasyUI 使用注意点

    前段时间做一个系统的服务端管理系统,使用了一下EasyUI.以下是我在使用中觉得需要注意的地方或者一些EasyUI中一些特别点的用法. 总结如下,与大家分享下,希望对初学者能有些作用. EasyUI ...

  8. hide(1000)跟show(1000)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. MyBatis(3.2.3) - Mapped statements: The INSERT statement, Autogenerated keys

    We can use the useGeneratedKeys and keyProperty attributes to let the database generate the auto_inc ...

  10. 日入过百优质消除手游数据分享—萌萌哒包子脸爱消除(游戏开发引擎:libgdx)

    从2014年开始,消除游戏异常火爆,从消除小星星到腾讯的天天消除都赢得了海量用户.目前,各大市场上开心消消乐等游戏依旧火爆.消除游戏一直持续保持着女性和孩子的主流游戏地位.虽然市场上消除游戏种类很多, ...