4.5 派生类的构造函数与析构函数
派生类继承了基类的成员,实现了代码的重复利用,但是继承的目的更主要的是功能的扩充。基类的构造函数和析构函数不能被继承。如果在派生类中需要对新增加的成员进行初始化,则需要加入派生类的构造函数。同样派生类也需要添加析构函数来实现一些结束工作。
4.5.1 派生类构造函数和析构函数的执行顺序
当创建对象时,编译系统会自动调用构造函数。当撤销对象时,编译系统会自动调用析构函数。当创建派生类的对象时,首先执行基类的构造函数,然后执行派生类的构造函数。当撤销对象时,则先执行派生类的析构函数,然后再执行基类的析构函数。
【示例4.20】 定义基类和派生类,查看构造函数和析构函数的调用次序。
- #include"iostream.h"
- class A
- {
- public:
- A()
- {cout<<"基类的构造函数"<<endl;}
- ~A()
- {cout<<"基类的析构函数"<<endl;}
- };
- class B:public A
- {
- public:
- B()
- {cout<<"派生类的构造函数"<<endl;}
- ~B()
- {cout<<"派生类的析构函数"<<endl;}
- };
- void main()
- {
- B p;
- }
程序输出结果如下所示。
- 基类的构造函数
- 派生类的构造函数
- 派生类的析构函数
- 基类的析构函数
分析:在定义对象时,系统会自动调用构造函数,而撤销对象时则会调用析构函数。在派生类中需要对基类的构造函数和析构函数进行处理。通过上面的例子可以清楚地看到在派生类中构造函数和析构函数的调用次序。如果有层派生时,首先调用基类的构造函数,然后逐层向上调用构造函数。析构函数的执行顺序与构造函数的调用次序相反。
【示例4.21】 多层派生构造函数和析构函数的执行次序。
- #include"iostream.h"
- class A
- {
- public:
- A()
- {cout<<"基类的构造函数"<<endl;}
- ~A()
- {cout<<"基类的析构函数"<<endl;}
- };
- class B:public A
- {
- public:
- B()
- {cout<<"派生类B的构造函数"<<endl;}
- ~B()
- {cout<<"派生类B的析构函数"<<endl;}
- };
- class C:public B
- {
- public:
- C()
- {cout<<"派生类C的构造函数"<<endl;}
- ~C()
- {cout<<"派生类C的析构函数"<<endl;}
- };
- void main()
- {
- C c;
- }
程序输出结果如下:
- 基类的构造函数
- 派生类B的构造函数
- 派生类C的构造函数
- 派生类C的析构函数
- 派生类B的析构函数
- 基类的析构函数
通过上面的例子可以清楚地看到多层派生时的构造函数和析构函数依次被调用的顺序。在多层派生的情况下需要从底层开始执行构造函数,撤销对象时,则从高层撤销对象。