构造函数
无参数构造函数
如果创建一个类你没有写任何构造函数,则系统会自动生成默认的无参构造函数,函数为空,什么都不做
只要你写了一个其他的某一种构造函数(非无参构造函数),系统就不会再自动生成这样一个默认的构造函数,如果希望有一个这样的无参构造函数,则需要自己显示地写出来
一般构造函数(也称重载构造函数)
一般构造函数可以有各种参数形式,一个类可以有多个一般构造函数,前提是参数的个数或者类型不同(基于c++的重载函数原理)
复制构造函数(也称为拷贝构造函数)
主要应用于使用一个已存在的对象去初始化一个新对象,使新对象的属性和该对象保持一致。
若用户未定义拷贝构造函数,编译器就自动提供一个默认的复制构造函数,其作用仅是简单地复制类中的每个数据成员;为了安全起见,类设计者需要提供拷贝构造函数;
拷贝构造函数一般形式:
类名(const 类名& 对象名)
形如:CComplex(const CComplex& srcObj)
在以下三种情况下,拷贝构造函数将被调用;
- 建立新对象
使用一个已存在对象num,初始化即将要被创建的新对象,可以有以下两种形式:
CComplex num1(num); //形式1
CComplex num2=num; //形式2
- 函数形参为类对象
在函数调用时需要将实参对象完整地传递给形参,系统将默认调用拷贝构造函数,建立一个实参的拷贝,这样形参对象和实参对象将具有相同的属性值;
需要注意的是,仅形参是按值传递时才会进行对象拷贝,若是传递引用,不会进行对象拷贝
形如:
//按值传递,复制对象
static void TransByValue(CComplex obj)
//传递引用,不复制对象
static void TransByRefence(const CComplex& obj)
- 函数返回值是类对象
当一个函数返回值是一个类对象时,在该函数返回调用处时,系统会将函数中的对象复制一份到别的地方,即使返回值没有被使用;
形如:
static CComplex GetObj()
{
CComplex ret(10,10);
return ret;
}
转换构造函数
转换构造函数的作用是将一个其他类型的数据转换为一个类的对象。转换构造函数也是一种构造函数,它遵循构造函数的一般原则,我们通常把仅有一个参数的构造函数用作类型转换,所把它称为转换构造函数。
转换构造函数中的类型数据可以是普通类型,也可以是类类型,其一般形式如下:
类名(指定类型的数据)
C++ 构造函数后加冒号
冒号后的内容是初始化成员列表,一般有三种情况:
- 1、对含有对象成员的对象进行初始化,例如,
类line有两个私有对象成员startpoint、endpoint,line的构造函数写成:
line(int sx,int sy,int ex,int ey):startpoint(sx,sy),endpoint(ex,ey){……}
初始化时按照类定义中对象成员的顺序分别调用各自对象的构造函数,再执行自己的构造函数
- 2、对于不含对象成员的对象,初始化时也可以套用上面的格式,例如,
类rectangle有两个数据成员length、width,其构造函数写成:
rectangle():length(1),width(2){}
rectangle(int x,int y):length(x),width(y){}
- 3、对父类进行初始化,例如,
CDlgCalcDlg的父类是MFC类CDialog,其构造函数写为:
CDlgCalcDlg(CWnd\* pParent ): CDialog(CDlgCalcDlg::IDD, pParent)
其中IDD是一个枚举元素,标志对话框模板的ID
使用初始化成员列表对对象进行初始化,有时是必须的,有时是出于提高效率的考虑
浅拷贝与浅拷贝的区别:
在使用一个对象对另一个对象初始化或赋值时,若对象包含指针成员变量,则需要手动的编写拷贝构造函数实现深拷贝,调用编译器的内部默认的拷贝构造函数则只能实现浅拷贝操作。
【浅拷贝】只是增加了一个指针,指向已存在对象的内存。
【深拷贝】是增加了一个指针,并新开辟了一块空间,让指针指向这块新开辟的空间。
【浅拷贝】在多个对象指向一块空间的时候,释放一个空间会导致其他对象所使用的空间也被释放了,再次释放便会出现错误
对象拷贝和对象赋值的区别
对象的赋值是对一个已经存在的对象进行重新赋值,因此必须先定义被赋值的对象,才能进行赋值;
对象的拷贝是在从无到有建立一个新对象,并使这个新对象和已有对象完全相同;
例如:
CComlex num1(1,1);
CCompex num2(2,2);
//对象赋值 使对象num2的值和对象num1一致,调用进行operator=运算符重载
num2 = num1;
//对象拷贝,利用对象num2创建新对象num3;
CCompex num3 = num2;
派生类和基类构造和析构函数
1).在调用派生类构造函数之前,系统会先调用基类的构造函数;如果派生类构造函数列表中包含对基类子对象成员的初始化(如上例中的monitor),每个基类子对象初始化时也要调用一次基类构造函数;最后才是派生类调用自身的构造函数来初始化自身新增的成员(如上例中的age,addr)。执行顺序就是派生类构造函数列表顺序:
2).正如派生类不能继承基类的构造函数,派生类也不能继承基类的析构函数,派生类的清理工作由派生自身析构函数负责,基类的清理工作由基类析构函数负责。
析构函数的调用顺序正好和构造函数调用顺序相反,即先调用派生类析构函数清理新增的成员,再调用子对象析构函数(基类析构函数)清理子对象,最后再调用基类析构函数清理基类成员。
析构函数
当对象超出作用域或动态分配的对象被删除时,将自动调用析构函数。
析构函数可用于释放对象时构造或在对象的生命期中所获取的资源。
不管类是否定义了自己的析构函数,编译器都自动执行类中非static 数据成员的析构函数。
- (1)、析构函数没有返回值和参数列表
- (2)、析构函数不能重载
- (3)、析构函数由系统自动调用,不能显式调用
- (4)、析构函数可以是inline函数
- (5)、析构函数应该设置为类的公有成员
- (6)、每个类有应该有一个析构函数,如果没有显式定义,那么系统会自动生成一个默认的析构函数
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。