派生类的构造函数和析构函数
基类的构造函数和析构函数不能被继承。
在派生类中,如果派生类新增的成员进行初始化,就必须加入新的构造函数。与此同时,对所有从基类继承下来的成员的初始化工作还是由基类的构造函数完成,必须在派生类中对基类的构造函数所需要的参数进行设置。同样,对派生类对象的扫尾,清理工作也需要加入析构函数。
首先看下面例子:
class A //默认构造函数为空
{
public:int x;
};
class B:public A //默认构造函数为空
{
public:int y;
};
当创建B类对象b1后,对象b1可以访问下x,y这两个成员。那么是否可以认为b1实际上是下面C类的对象呢?
class C
{
public:int x,y;
};
若利用C类创建对象c1,从成员访问权限上看,对象b1和c1没有差别。但是b1的x和c1的x不同,它继承于基类。由于派生类不能继承父类的构造函数和析构函数,因此对象b1的x占据的内存区域只能通过基类的构造函数初始化。同样,销毁对象时,b1的x占据的内存也只能由基类的析构函数进行清理。而对象c1的x是由C类构造函数初始化,由C类析构函数进行清理工作的。因此b1和c1仅仅是表面相似而已。由于派生类构造过程涉及基类构造函数的调用,因此其构造函数比较复杂。
1、构造函数
派生类构造函数的一般形式为
派生类::派生类(参数总表)::基类1(参数表1),……,基类n(参数表n),内嵌对象1(对象参数表1),……,内嵌对象m(对象参数表m){
派生类新增加成员的初始化;
}
这个声明形式很复杂,应该注意以下几点:
①对于基类继承的数据成员,应采用基类构造函数初始化,并且应放在派生类构造函数的初始化列表中,不应放到构造函数体中初始化。
②参数总表包括全部基类和全部内嵌对象的所有参数,同时也包含派生类新增数据成员的初始化参数。最后一个冒号后面的基类和内嵌对象的参数全部取自前面的参数总部。
③当派生类使用基类无参数的默认构造函数初始化继承的数据成员时,初始化列表中就不存在“基类(参数表)”的初始化部分。
④当派生类中无内嵌对象或者内嵌对象使用无参数的默认构造函数时,初始化列表中就不存在“内嵌对象(参数表)”的初始化列表部分。
⑤当基类有待参数的构造函数时,派生类应当定义构造函数,提供一个将参数传递给基类的构造函数的途径
派生类构造函数的执行次序为:执行基类构造函数——执行内嵌对象的构造函数——执行派生类构造函数体的内容
派生类析构函数的执行次序为:执行派生类析构函数——执行内嵌对象的析构函数——执行基类析构函数
派生类构造函数和析构函数的执行
代码分析:
从输出结果可以清楚地看出,构造函数执行顺序为先祖先(Person 张三),后客人(Person 王五),最后自己(Employee),这里Wang是Person类只的一个对象,被派生类Emoloyee所有。
同时,从上面的输出结果中可以看出,析构函数的执行次序恰好与构造函数相反,先执行自身(Employee)的析构函数,而后是客人(Person 王五),最后祖先(Person 张三)