继承的构造和析构

Posted chengeputongren

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了继承的构造和析构相关的知识,希望对你有一定的参考价值。

  • 思考问题:如何初始化父类成员?父类构造函数和子类构造函数有什么关系呢?
  • 子类对象的构造
  1. 子类中可方式以定义构造函数
  2. 子类构造函数必须对继承而来的成员进行初始化:
            1)直接通过初始化列表或者赋值的方式进行初始化 
            2)调用父类构造函数进行初始化
  • 父类构造函数在子类中的调用方式
  1. 默认调用:适用于无参构造函数和使用默认参数的构造函数
  2. 显示调用:通过初始化列表进行调用,适用于所有父类构造函数
  3. 如果子类没有显示调用,那么在父类中需要有无参构造函数

技术图片

class Child : public Parent
{
public:
        //隐式调用父类中的无参构造函数
    Child()
    {
        cout << "Child()" << endl;
    }
    //显式调用父类构造函数
    Child(string _str) : Parent(_str)
    {
        name = _str;
        cout << "Child(string _str):"<< name<< endl;
    }
};
  • 构造规则
  1. 子类对象在创建时会首先调用父类的构造函数
  2. 先执行父类构造函数再执行子类的构造函数
  3. 父类构造函数可以被隐式调用或者显式调用
  • 对象创建时构造函数的调用顺序
  1. 调用父类的构造函数
  2. 调用成员变量的构造函数
  3. 调用类自身的构造函数
  4. 口诀:先父母,后客人,再自己。
  • 实验
// 继承的构造和析构.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <string>
using namespace std;
class Grandfather
{
public:
    Grandfather()
    {
        cout << " Grandfather()" << endl;
    }
    Grandfather(string _str)
    {
        cout << "Grandfather(string _str):" << _str << endl;
    }
};
class Parent :public Grandfather
{
protected:
    string name;
public:
    Parent() : Grandfather("default")
    {
        cout << "Parent()" << endl;
    }
    Parent(string _str):Grandfather("Grandfather")
    {
        name = _str;
        cout << "Parent(string _str):"<<name << endl;
    }
};
class Child : public Parent
{
    Grandfather guest;
public:
    Child() : guest("default")
    {
        cout << "Child()" << endl;
    }
    //显式调用父类构造函数
    Child(string _str) : Parent("father"),guest("guest")
    {
        name = _str;
        cout << "Child(string _str):"<< name<< endl;
    }
};
int main()
{
    Child chenge("son");
}
  • 运行结果
        Grandfather(string _str):Grandfather
        Parent(string _str):father
        Grandfather(string _str):guest
        Child(string _str):son
  • 子类对象的析构
  1. 执行自身的析构函数
  2. 执行成员变量的析构函数
  3. 执行父类的析构函数
  • 实验:
 1 // 继承的构造和析构.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
 2 //
 3 #include <iostream>
 4 #include <string>
 5 using namespace std;
 6 class Grandfather
 7 {
 8     string name;
 9 public:
10     Grandfather()
11     {
12         cout << " Grandfather()" << endl;
13     }
14     Grandfather(string _str)
15     {
16         name = _str;
17         cout << "Grandfather(string _str):" << _str << endl;
18     }
19     ~Grandfather()
20     {
21         cout << "~Grandfather():" << name << endl;
22     }
23 };
24 class Parent :public Grandfather
25 {
26     string name;
27 public:
28     Parent() : Grandfather("default")
29     {
30         name = "default";
31         cout << "Parent()" << endl;
32     }
33     Parent(string _str):Grandfather("Grandfather")
34     {
35         name = _str;
36         cout << "Parent(string _str):"<<name << endl;
37     }
38     ~Parent()
39     {
40         cout << "~Parent():" << name << endl;
41     }
42 };
43 class Child : public Parent
44 {
45     string name;
46     Grandfather guest;
47 public:
48     Child() : guest("default")
49     {
50         name = "default";
51         cout << "Child()" << endl;
52     }
53     //显式调用父类构造函数
54     Child(string _str) : Parent("father"),guest("guest")
55     {
56         name = _str;
57         cout << "Child(string _str):"<< name<< endl;
58     }
59     ~Child()
60     {
61         cout << "~Child():" << name << endl;
62     }
63 };
64 int main()
65 {
66     Child chenge("son");
67 }
  • 运行结果
            Grandfather(string _str):Grandfather
            Parent(string _str):father
            Grandfather(string _str):guest
            Child(string _str):son
            ~Child():son
            ~Grandfather():guest
            ~Parent():father
            ~Grandfather():Grandfather
  • 小结
  1. 子类对象在创建时需要调用父类构造函数进行初始化
  2. 先执行父类构造函数然后执行成员的构造函数
  3. 父类构造函数显式调用需要在初始化列表中进行
  4. 子类对象在销毁时需要调用父类析构函数进行清理
  5. 析构顺序与构造顺序对称相反
 

以上是关于继承的构造和析构的主要内容,如果未能解决你的问题,请参考以下文章

C++继承中的构造和析构

继承机制中的构造器和析构器

继承的构造和析构

多继承的构造和析构函数调用顺序

继承和组合混搭的情况下,构造和析构函数的调用顺序

C++ 继承中构造和析构对象(面试题可能问)