C++ 构造函数与析构函数

构造函数

无参数构造函数

若是建立一个类你没有写任何构造函数,则系统会自动生成默认的无参构造函数,函数为空,什么都不作 c++

只要你写了一个其余的某一种构造函数(非无参构造函数),系统就不会再自动生成这样一个默认的构造函数,若是但愿有一个这样的无参构造函数,则须要本身显示地写出来安全

通常构造函数(也称重载构造函数)

通常构造函数能够有各类参数形式,一个类能够有多个通常构造函数,前提是参数的个数或者类型不一样(基于c++的重载函数原理)函数

复制构造函数(也称为拷贝构造函数)

主要应用于使用一个已存在的对象去初始化一个新对象,使新对象的属性和该对象保持一致。设计

若用户未定义拷贝构造函数,编译器就自动提供一个默认的复制构造函数,其做用仅是简单地复制类中的每一个数据成员;为了安全起见,类设计者须要提供拷贝构造函数;指针

拷贝构造函数通常形式:code

类名(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++ 构造函数后加冒号

冒号后的内容是初始化成员列表,通常有三种状况:

  • 一、对含有对象成员的对象进行初始化,例如,

类line有两个私有对象成员startpoint、endpoint,line的构造函数写成:

line(int sx,int sy,int ex,int ey):startpoint(sx,sy),endpoint(ex,ey){……}

初始化时按照类定义中对象成员的顺序分别调用各自对象的构造函数,再执行本身的构造函数

  • 二、对于不含对象成员的对象,初始化时也能够套用上面的格式,例如,

类rectangle有两个数据成员length、width,其构造函数写成:

rectangle():length(1),width(2){}
rectangle(int x,int y):length(x),width(y){}
  • 三、对父类进行初始化,例如,

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)、每一个类有应该有一个析构函数,若是没有显式定义,那么系统会自动生成一个默认的析构函数
相关文章
相关标签/搜索