【C++学习笔记】派生类的构造函数和析构函数

0x00 前言

文章中的文字可能存在语法错误以及标点错误,请谅解;

如果在文章中发现代码错误或其它问题请告知,感谢!

本文档为个人边学习边记录的C++笔记,非教程,笔记中会存在引用他人文章内容的部分,被引用的原文不会被特殊标记出来,但会在参考文档中给出原文链接。

0x01 构造函数

对象在使用之前必须初始化,因此构造派生类对象时,就要对基类成员对象和新增成员对象进行初始化。

基类的构造函数并没有继承下来,要完成这些工作,就必须给派生类添加新的构造函数。

派生类对于基类的很多成员对象是不能直接访问的,因此要完成对基类成员对象的初始化工作,需要通过调用基类的构造函数。

在构造派生类对象时,会首先调用基类的构造函数,来初始化它们的数据成员,然后按照构造函数初始化表列中指定的方式初始化派生类新增的成员对象,最后才执行派生类构造函数的函数体。

派生类构造函数的一般语法形式为:

派生类名::派生类名(参数表):基类名1(基类1初始化参数表),...,基类名n(基类n初始化参数表),成员对象名1(成员对象1参数初始化参数表),...,成员对象名m(成员对象名m初始化参数表)
{
	派生类构造函数的其他初始化操作;
}

对于默认构造函数的基类,可以不给出类名。同样,对于成员都西昂,如果时使用默认构造函数,也不需要写出对象名和参数表。

如果对基类初始化时,需要调用积累带有形参表的构造函数时,派生类就必须声明构造函数。

当派生类没有显示的构造函数时,系统会隐含生成一个默认构造函数,该函数会使用基类的默认构造函数对继承自基类的数据初始化,并且调用类类型的成员对象的默认构造函数,对这些成员对象初始化。

派生类构造函数执行的一般次序如下:
(1)调用基类构造函数,调用顺序按照它们被继承时声明的顺序(从左向右)
(2)对派生类新增的成员进行初始化,调用顺序按照它们在类中声明的顺序。
(3)执行派生类构造函数体中的内容。

例:派生类构造函数举例(多继承、含有内嵌对象)

#include <iostream>
using namespace std;

class Base1{
public:
	Base1(int i){cout << "Constructing Base1" << i << endl;}
}; 

class Base2{
public:
	Base2(int j){cout << "Constructing Base2" << j << endl;}
};

class Base3{
public:
	Base3(){cout << "Constructing Base3*"  << endl;}
};

class Derived:public Base2, public Base1, public Base3{
public:
	Derived(int a, int b, int c, int d):Base1(a), member2(d), member1(c), Base2(b){}

private:
	Base1 member1;
	Base2 member2;
	Base3 member3;
};

int main() {
	Derived obj(1, 2, 3, 4);
	return 0;
}

运行结果:

Constructing Base22
Constructing Base11
Constructing Base3*
Constructing Base13
Constructing Base24
Constructing Base3*

基类构造函数的调用顺序是按照派生类定义时的顺序,而内嵌对象的构造函数调用顺序应该是按照成员在类中声明的顺序

0x02 复制构造函数

对于一个类,如果程序员没有编写复制构造函数,编译系统会在必要时自动生成一个隐含的复制构造函数,这个隐含的复制构造函数会自动嗲用积累的复制构造函数,然后对派生类新增的成员对象一一直幸福之。

如果要为派生类编写复制构造函数,一般需要为积累相应的复制构造函数传递参数。例如,假设Derived类时Base类的派生类,Derived类的复制构造函数形式如下:

Derived::Derived(const Derived &v):Base(v){...}

0x03 析构函数

派生类析构函数的声明方法与没有继承关系的类中析构函数的生命方法完全相同,只要在函数体中负责把派生类新增的非对象成员的清理工作做好就够了系统会自己调用基类及对象成员的析构函数来对基类及对象成员进行清理。

派生类析析构函数的执行次序和构造函数正好相反,首先执行析构函数的函数体,然后对派生类新增的类型成员对象进行清理,最后对所有从基类继承来的成员进行清理。

例:派生类析构函数举例(多继承、含有嵌入对象)

#include <iostream>
using namespace std;

class Base1{
public:
	Base1(int i){cout << "Constructing Base1" << i << endl;}
	~Base1(){cout << "Destructing Base1" << endl;}
}; 

class Base2{
public:
	Base2(int j){cout << "Constructing Base2" << j << endl;}
	~Base2(){cout << "Destructing Base2" << endl;}
};

class Base3{
public:
	Base3(){cout << "Constructing Base3*"  << endl;}
	~Base3(){cout << "Destructing Base3" << endl;}
};

class Derived:public Base2, public Base1, public Base3{
public:
	Derived(int a, int b, int c, int d):Base1(a), member2(d), member1(c), Base2(b){}

private:
	Base1 member1;
	Base2 member2;
	Base3 member3;
};

int main() {
	Derived obj(1, 2, 3, 4);
	return 0;
}

运行结果:

Constructing Base22
Constructing Base11
Constructing Base3*
Constructing Base13
Constructing Base24
Constructing Base3*
Destructing Base3
Destructing Base2
Destructing Base1
Destructing Base3
Destructing Base1
Destructing Base2

程序执行时,首先执行派生类构造函数,然后执行派生类的析构函数。

《C++语言程序设计(第4版)》书上所有章节出现的示例源代码随着学习的深入会陆续上传至github,代码为个人手动输入并通过编译,有的示例代码可能没有注释:https://github.com/fyw4/C-plus-plus-learning-example

以上。

参考文档:
郑莉 董渊 何江舟.《C++语言程序设计(第4版)》[M].北京:清华大学出版社。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值