• 【C++】继承 ⑧ ( 继承 + 组合 模式的类对象 构造函数 和 析构函数 调用规则 )






    一、继承 + 组合 模式的类对象 构造函数和析构函数调用规则




    1、场景说明


    如果一个类

    • 继承了 基类 ,
    • 在类中 维护了一个 其它类型 的 成员变量 ,

    那么 该类 的 构造 与 析构 , 就需要涉及到

    • 类 本身 的 构造函数 和 析构函数 ,
    • 父类 的 构造函数 和 析构函数 ,
    • 类 成员变量 的 构造函数 和 析构函数 ;

    2、调用规则


    在 继承 + 组合 的情况下 , 构造函数 与 析构函数 调用规则如下 :

    • 构造函数 : 父类 -> 成员 -> 自身 ;
      • 首先 , 调用 父类 构造函数 ;
      • 然后 , 调用 成员 构造函数 ; 也就是 成员变量 类型的 构造函数 ;
      • 最后 , 调用 自己 构造函数 ; 自身定义的 构造函数 ;
    • 析构函数 : 自身 -> 成员 -> 父类 ;
      • 首先 , 调用 自己 析构函数 ; 自身定义的 析构函数 ;
      • 然后 , 调用 成员 析构函数 ; 也就是 成员变量 类型的 析构函数 ;
      • 最后 , 调用 父类 析构函数 ;




    二、完整代码示例分析




    1、代码分析


    在下面的代码中 ,

    继承关系 : C 类 继承了 B 类 class C : public B , B 类 继承了 A 类 class B : public A ;

    组合关系 : D 类 是一个普通类 , 在 C 类中维护了一个 D 类成员变量 ;

    class C : public B {
    public:
    	C(int a, int b, int c) : B(a, b)
    	{
    		this->z = c;
    		cout << "C 构造函数调用" << endl;
    	}
    	~C()
    	{
    		cout << "C 析构函数调用" << endl;
    	}
    public:
    	int z;
    	D d;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    可根据下面的调用规则 , 分析出 C 类对象中 , 涉及到的 父类构造/析构函数 , 自身构造/析构函数 , 成员变量 构造/析构函数 的调用顺序 ;

    • 构造函数调用顺序 : 父类 -> 成员 -> 自身 ;
    • 析构函数调用顺序 : 自身 -> 成员 -> 父类 ;

    2、代码示例


    代码示例 :

    #include "iostream"
    using namespace std;
    
    class A {
    public:
    	A(int a)
    	{
    		this->x = a;
    		cout << "A 构造函数调用" << endl;
    	}
    	~A()
    	{
    		cout << "A 析构函数调用" << endl;
    	}
    public:
    	int x;
    };
    
    class B : public A {
    public:
    	B(int a, int b) : A(a)
    	{
    		this->y = b;
    		cout << "B 构造函数调用" << endl;
    	}
    	~B()
    	{
    		cout << "B 析构函数调用" << endl;
    	}
    public:
    	int y;
    };
    
    class D
    {
    public:
    	D()
    	{
    		cout << "D 构造函数调用" << endl;
    	}
    	~D()
    	{
    		cout << "D 析构函数调用" << endl;
    	}
    };
    
    class C : public B {
    public:
    	C(int a, int b, int c) : B(a, b)
    	{
    		this->z = c;
    		cout << "C 构造函数调用" << endl;
    	}
    	~C()
    	{
    		cout << "C 析构函数调用" << endl;
    	}
    public:
    	int z;
    	D d;
    };
    
    int main() {
    
    	C obj(1, 2, 3);
    
    	cout << "obj.x = " << obj.x <<
    		" , obj.y = " << obj.y <<
    		" , obj.z = " << obj.z << endl;
    
    
    	// 控制台暂停 , 按任意键继续向后执行
    	system("pause");
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76

    执行结果 : 下面的代码中 , 分析构造函数调用顺序 ;

    • A 和 B 的构造函数 , 是 父类构造函数 ;
    • D 构造函数 , 是 成员构造函数 ;
    • C 构造函数 , 是 自身构造函数 ;

    构造函数的调用顺序为 : 父类 -> 成员 -> 自身 , 符合上述的调用原则 ;

    然后分析 析构函数 调用顺序 ;

    • C 析构函数 , 是 自身构造函数 ;
    • D 析构函数 , 是 成员构造函数 ;
    • A 和 B 的析构函数 , 是 父类构造函数 ;

    析构函数的调用顺序为 : 自身 -> 成员 -> 父类 , 符合上述的调用原则 ;

    A 构造函数调用
    B 构造函数调用
    D 构造函数调用
    C 构造函数调用
    obj.x = 1 , obj.y = 2 , obj.z = 3
    Press any key to continue . . .
    C 析构函数调用
    D 析构函数调用
    B 析构函数调用
    A 析构函数调用
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

  • 相关阅读:
    Docker安装MySQL数据库
    java计算机毕业设计潮流奢侈品购物网站源码+mysql数据库+系统+lw文档+部署
    zabbix
    游戏中排行榜算法研究
    鸿蒙开发系列教程(二十四)--List 列表操作(3)
    如何将高效设计应用于 DAO?
    【408专项篇】C语言笔记-第四章(选择与循环)
    基于Java毕业设计养老机构管理信息系统源码+系统+mysql+lw文档+部署软件
    计算机毕业设计ssm+vue基本微信小程序的校园生活助手系统
    由浅入深学会白盒测试用例设计
  • 原文地址:https://blog.csdn.net/han1202012/article/details/133982422