派生类对象的构造函数与析构函数

1、派生类调用基类构造函数的两种方式
我们不能够直接在派生类的构造函数内部初始化派生类所包含的基类成员,因为派生类成员函数内部不能访问基类的私有成员。因此,我们应该使用初始化列表的方式初始化派生类所包含的基类成员。
在执行一个派生类的构造函数(初始化)之前,总是先执行基类(初始化)的构造函数。因此,在创建派生类的对象时,需要先调用基类的构造函数:初始化派生类对象中从基类继承的成员。

Bug::Bug( int legs, int color)
{
	nLegs = legs;
	nColor = color;
}
//错误的FlyBug构造函数
FlyBug::FlyBug ( int legs,int color, int wings)
{
	nLegs = legs;// 派生类成员函数不能直接访问基类私有成员
	nColor = color; // 派生类成员函数不能直接访问基类私有成员
	nType = 1; // 派生类成员函数能直接访问基类公有成员
	nWings = wings;
}
//正确的FlyBug构造函数:
//使用初始化列表初始化派生类所包含的基类的成员
FlyBug::FlyBug ( int legs, int color, int wings):Bug( legs, color)
{
	nWings = wings;
}

int main() {
	FlyBug fb ( 2,3,4);
	fb.PrintBug();
	fb.nType = 1;
	fb.nLegs = 2 ; // error.
	return 0;
}

派生类对象调用基类构造函数的两种方式(派生类对象初始化所包含基类成员的两种方式):

  • 显式方式:在派生类的构造函数中,为基类的构造函数提供参数.
  • 隐式方式:在派生类的构造函数中,省略基类构造函数时,派生类的构造函数则自动调用基类的默认构造函数.
//显式方式举例
derived::derived(arg_derived-list):base(arg_base-list)

2、派生类和基类的初始化以及析构顺序
在执行一个派生类的构造函数(初始化)之前,总是先执行基类(初始化)的构造函数。派生类的析构函数被执行时,执行完派生类的析构函数后,自动调用基类的析构函数。

3、包含成员对象的派生类的构造函数的写法,以及构造函数和析构函数的执行顺序
(1)写法

class Bug {
private :
	int nLegs;
	int nColor;
public:
	int nType;
	Bug ( int legs, int color);
		void PrintBug (){ };
	};
class Skill {
public:
	Skill(int n) { }
};
class FlyBug: public Bug {
	int nWings;
	Skill sk1, sk2;
public:
	FlyBug( int legs, int color, int wings);
};
FlyBug::FlyBug( int legs, int color, int wings):
	Bug(legs,color),sk1(5),sk2(color) ,nWings(wings) {
}
/*
Base 3 constructed
Derived constructed
Derived destructed
Base 3 destructed
*/

(2)执行顺序
封闭派生类对象的构造函数的执行顺序

  • 先执行基类的构造函数,用以初始化派生类对象中从基类 继承的成员;
  • 再执行成员对象类的构造函数,用以初始化派生类对象中 成员对象。
  • 最后执行派生类自己的构造函数

封闭派生类对象消亡时析构函数的执行顺序

  • 先执行派生类自己的析构函数
  • 再依次执行各成员对象类的析构函数
  • 最后执行基类的析构函数
  • 析构函数的调用顺序与构造函数的调用顺序相反。
posted @ 2019-12-05 10:31  江南又一春  阅读(582)  评论(0编辑  收藏  举报