一、简单派生类的构造函数

派生类构造函数一般形式:

派生类构造函数名(总参数表):积累构造函数名(实际参数列表)

{

          派生类中新增数据成员初始化语句

}

看下面代码例子:

class student                        //基类 
{
	public:
		student(int x, double y, string z) //定义基类构造函数 
		{
			a = x;
			b = y;
			c = z;
		}
        student(){}                  //默认构造函数
		~student(){}                 //基类析构函数 
	protected:
		int a;
		double b;
		string c;
};

class student1 : public student      //声明共用派生类student1 
{
	public:
		student1(int x, double y, string z, int m, float n):student(x, y, z)
		   //*定义派生类构造函数(这里有基类构造函数和派生类构造函数,先调用基类构造函数,再调用派生类构造函数) (这里调用函数循序按照一定方式来,后面会总结)
   //补充:这里可以写成这样 student1(int x, double y, string z, int m, float n):student() 当然如果这样写,相当于调用了默认构造函数,这样student里的成员数据就传不过来了,传的是默认构造函数,x,y,z也就没用了
		{
			d = m;                   //在派生类构造函数中给新增的数据成员初始化 
			e = n;
		}
		~student1(){}                //派生类析构函数 
	private:
		int d;
		float e;
};

调用派生类构造函数还有一种写法:

public:
		student1(int x, double y, string z, int m, float n):student(x, y, z),d(m),e(n)
		{
			
		}

 

二、有子对象的派生类构造函数

如果类的数据成员除了标准数据类型外,还包含类对象,这种被包含的对象就叫“子对象”,即对象中的对象

还按刚才的例子说明,积累不变,派生类增加子对象

class student1 : public student      
{
	public:
		student1(int x, double y, string z, int x1, double y1, string z1, int m, float n):student(x, y, z), monitor(f, g, h) 
		        //这里加入了子对象,调用顺序先是基类构造函数,再是子对象构造函数,最后是派生类构造函数,初始化新增成员                     
		{
			d = m;                  
			e = n;
		}
		~student1(){}               
	private:
		int d;
		float e;
		student monitor;             //定义一个student类型的子对象 
};

关于子对象的问题这里不会详细讲解,以后会详细讲解

总结起来:

1.派生类构造函数一般形式:

派生类构造函数名(总参数表):基类构造函数名(参数列表),子对象名(参数列表)

{

            派生类中新增数据成员初始化语句

}

2.执行派生类构造函数顺序:

(1)调用基类构造函数,初始化基类数据成员

(2)调用子对象构造函数,初始化子对象数据成员

(3)再执行派生类自身的构造函数,初始化自身新增的数据成员

 

三、多层派生时的构造函数

当在此基础上再增加一个派生类来继承以上所有类怎么做呢?

很简单,如下所示,只需要在让一个派生类中再加入新元素即可:

class student2 : public student1
{
	public:
		student2(int x, double y, string z, int m, float n, int q) : student1(x, y, z, m, n) //在student1的基础上加入student2的新成员变量
		{
			f = q;	
		}
		~student2(){}   //student2的析构函数
	private:
		int f;
};

这里有一点需要注意的是:

在调用student2的构造函数时,会先调用student1的构造函数,在调用student1的构造函数时又会先调用student的构造函数

所以student2的初始化顺序是:

先初始化基类的数据成员,再初始化student1的数据成员,最后初始化student2的数据成员

 

四、派生类构造函数的特殊形式

1.当不需要对派生类新增成员进行任何初始化操作,派生类构造函数函数体内可以为空

class student1 : public student      //声明共用派生类student1 
{
	public:
		student1(int x, double y, string z):student(x, y, z)
		{                      //对新增的d,e不赋任何初值,只继承了基类中的初始化
		}
		~student1(){}                //派生类析构函数 
	private:
		int d;
		float e;
};

2.既然可以选择继承基类中的初始化也可以不继承,比如:不继承基函数自定义初始化,继承默认构造函数(见一中代码里的补充)

当然也可以不写基类构造函数,这样派生类构造函数就没有向基类构造函数传递参数的任务

 

五、派生类中的析构函数

析构函数只有一点记住即可

析构函数调用的顺序和构造函数正好相反:先执行派生类自己的析构函数,对派生类新增的成员进行清理,然后在调用子对象的析构函数,对子对象进行清理,最后调用基类的析构函数,对基类进行清理

收藏 打印