派生类的构造函数赋值和析构函数执行顺序
基类的构造函数和析构函数是不能被继承的
1、如果基类没有定义构造函数,派生类也可以不定义构造函数,使用默认的构造函数,其新增成员的初始化可以用其他公有函数来实现.
2.如果基类中定义了缺省构造函数或根本没有定义任何一个构造函数(此时,由编译器自动生成缺省构造函数)时,在派生类构造函数的定义中可以省略对基类构造函数的调用,即省略<基类名>(<参数表>)。
3、如果基类定义了带有形参表的构造函数派生类就必须加入新的构造函数,提供一个将参数传递给基类构造函数的途径,保证在基类进行初始化时能够获得必要的数据因此,如果基类的构造函数定义了一个或多个参数时,派生类必须定义构造函数。
4.对派生类对象的清理工作也需要加入新的析构函数。
5. 子对象的情况与基类相同。
派生类的数据成员由所有基类的数据成员与派生类新增的数据成员共同组成,如果派生类新增成员中包括其他类的对象(子对象),派生类的数据成员中实际上还间接包括了这些对象的数据成员。因此,构造派生类的对象时,必须对基类数据成员、新增数据成员和成员对象的数据成员进行初始化。派生类的构造函数必须要以合适的初值作为参数,隐含调用基类和新增对象成员的构造函数,来初始化它们各自的数据成员,然后再加入新的语句对新增普通数据成员进行初始化。
派生类构造函数的一般格式如下:
<派生类名>::<派生类名>(<参数表>) : <基类名1>(<参数表1>),
……,
<基类名n>(<参数表n>),
<子对象名1>(<参数表n+1>),
……,
<子对象名m>(<参数表n+m>)
{
派生类新增成员的初始化函数语句;
派生类构造函数的一般格式如下:
<派生类名>::<派生类名>(<参数表>) : <基类名1>(<参数表1>),
……,
<基类名n>(<参数表n>),
<子对象名1>(<参数表n+1>),
……,
<子对象名m>(<参数表n+m>)
{
派生类新增成员的初始化函数语句;
}
说明:
(1) 对基类成员和子对象成员的初始化必须在成员初始化列表中进行,新增成员的初始化既可以在成员初始化列表中进行,也可以在构造函数体中进行。
(2) 派生类构造函数必须对这三类成员进行初始化,其执行顺序如下所述。
. 调用基类构造函数;
. 调用子对象的构造函数;
. 派生类的构造函数体;
说明:
(1) 对基类成员和子对象成员的初始化必须在成员初始化列表中进行,新增成员的初始化既可以在成员初始化列表中进行,也可以在构造函数体中进行。
(2) 派生类构造函数必须对这三类成员进行初始化,其执行顺序如下所述。
. 调用基类构造函数;
. 调用子对象的构造函数;
. 派生类的构造函数体;
(3) 派生类析构函数的执行顺序与构造函数相反:其派生类的析构函数和没有继承关系的类中析构函数的定义完全相同,只要在函数体中负责把派生类新增的非对象成员的清理工作做好就够了,系统会自己调用基类及成员对象的析构函数,来对基类及对象成员进行清理。
(3) 当派生类有多个基类时,处于同一层次的各个基类的构造函数的调用顺序取决于定义派生类时声明的顺序(自左向右),而与在派生类构造函数的成员初始化列表中给出的顺序无关。
(4) 当派生类中有多个子对象时,各个子对象构造函数的调用顺序也取决于在派生类中定义的顺序(自前至后),而与在派生类构造函数的成员初始化列表中给出的顺序无关。
(5) 如果派生类的基类也是一个派生类,则每个派生类只需负责其直接基类的构造,依次上溯。
(6) 当所有的基类和子对象的构造函数都可以省略时,可以省略派生类构造函数的成员初始化列表。
(5) 如果派生类的基类也是一个派生类,则每个派生类只需负责其直接基类的构造,依次上溯。
(6) 当所有的基类和子对象的构造函数都可以省略时,可以省略派生类构造函数的成员初始化列表。
#include<iostream.h>
class base1
{
private:
int i;
public:
base1(int b){i=b;cout<<"constructing base1"<<" "<<i<<endl;}
~base1(){cout<<"destructing base1"<<endl;}
};
class base1
{
private:
int i;
public:
base1(int b){i=b;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;}
};
{
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 derive:public base2,public base1,public base3
{
private:
{
private:
int ee;
base1 memberbase1;
base2 memberbase2;
base3 memberbase3;
public:
derive(int a,int b,int c,int d,int e):base1(a),memberbase2(d),memberbase1(c),base2(b){ee=e;cout<<"constructing derive"<<" "<<ee<<endl;}
~derive(){cout<<"destructing derive"<<endl;}
};
base1 memberbase1;
base2 memberbase2;
base3 memberbase3;
public:
derive(int a,int b,int c,int d,int e):base1(a),memberbase2(d),memberbase1(c),base2(b){ee=e;cout<<"constructing derive"<<" "<<ee<<endl;}
~derive(){cout<<"destructing derive"<<endl;}
};
void main()
{
derive object(2,4,6,8,10);
}
运行结果
constructing base2 4
constructing base1 2
constructing base3
constructing base1 6
constructing base2 8
constructing base3
constructing derive 10
destructing derive
destructing base3
destructing base2析构函数的定义
destructing base1
destructing base3
destructing base1
destructing base2
分析:
构造函数的调用顺序:1.调用基类的构造函数(声明顺序): public base2,public base1,public base3
2.调用内嵌对象的构造函数(声明顺序): base1 memberbase1;
base2 memberbase2;
base3 memberbase3;
2.调用内嵌对象的构造函数(声明顺序): base1 memberbase1;
base2 memberbase2;
base3 memberbase3;
3.调用派生类本身构造函数。
析构函数的调用顺序:与构造函数相反
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论