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

  派生类的数据成员由所有基类的数据成员与派生类新增的数据成员共同组成,如果派生类新增成员中包括其他类的对象(子对象),派生类的数据成员中实际上还间接地包括了这些对象的数据成员。 因此, 构造派生类的对象时, 必须对基类数据成员、 新增数据成员和成员对象的数据成员进行初始化。 派生类的构造函数必须要以合适的初值作为参数,隐含调用基类和新增对象成员的构造函数,然后再加入新的语句对新增普通数据成员进行初始化。来初始化它们各自的数据成员,然后再加入新的语句对新增普通数据成员进行初始化。

对派生类的构造函数几点说明

  1. 对基类成员和子对象成员的初始化必须在成员初始化列表中进行,新增成员的初始化既可以在成员初始化列表中进行, 也可以在构造函数体中进行。
  2. 派生类构造函数必须对这 3 类成员进行初始化, 其执行顺序是这样的:心先调用基类构造函数;@再调用子对象的构造函数;@最后调用派生类的构造函数体。
  3. 当派生类有多个基类时, 处于同一层次的各个基类的构造函数的调用顺序取决于定义派生类时声明的顺序(自左向右), 而与在派生类构造函数的成员初始化列表中给出的顺序无关。
  4. 如果派生类的基类也是一个派生类, 则每个派生类只需负责其直接基类的构造, 依次上溯。
  5. 当派生类中有多个子对象时, 各个子对象构造函数的调用顺序也取决于在派生类中定义的顺序(自前至后), 而与在派生类构造函数的成员初始化列表中给出的顺序无关。
  6. 派生类构造函数提供了将参数传递给基类构造函数的途径, 以保证在基类进行初始化时能够获得必要的数据。 因此,如果基类的构造函数定义了一个或多个参数时, 派生类必须定义构造函数。
  7. 如果基类中定义了默认构造函数或根本没有定义任何一个构造函数(此时由编译器自动生成默认构造函数) 时, 在派生类构造函数的定义中可以省略对基类构造函数的调用,即省略”<基类名>(<参数表>)” 这个语句。
  8. 子对象的情况与基类相同。
  9. 当所有的基类和子对象的构造函数都可以省略时, 可以省略派生类构造函数的成员
  10. 如果所有的基类和子对象构造函数都不需要参数, 派生类也不需要参数时, 派生类构造函数可以不定义。

代码样例

CStuden.h

 #pragma once
 #include <iostream>
 #include <string>
using namespace std;
class CStudent
{
public:
	//CStudent();
	CStudent(int n,string nam,char s);
	~CStudent();
protected:
	int num;
	string name;
	char sex;
};

CStuden.cpp

#include "CStudent.h"


//
//CStudent::CStudent()
//{
//}


CStudent::CStudent(int n, string nam, char s)
{
	num = n;
	name = nam;
	sex = s;
}

CStudent::~CStudent()
{
}

CStuden1.h

#pragma once
#include "CStudent.h"
class CStudent1 :
	public CStudent
{
public:
	/*CStudent1();*/
	CStudent1(int n, string nam, char s, int a, string ad) :CStudent(n, nam, s) {
		age = a;
	    addr = ad;
		
	};
	~CStudent1();
	void show();
private:
	int age;
	string addr;
};

CStuden1.cpp

#include "CStudent1.h"
CStudent1::~CStudent1()
{
}

void CStudent1::show()
{
	cout << "num:" << num << endl;
	cout << "name:" << name << endl;
	cout << "sex:" << sex << endl;
	cout << "address" << addr << endl;
}

main.cpp

#include "CStudent.h"
#include "CStudent1.h"
int main()
{
	CStudent1 stud1(10010, "wang_li", 'f', 19, "115 beijing road,shanghai");
	CStudent1 stud2(10011, "zhang-fun", 'm', 21, "213 shanghai road,beijing");
	stud1.show();
	stud2.show();
	system("pause");
}

运行结果

num: 10010 
name: Wang-li sex: f 
age: 19 
address: 115 Beijing Road,Shanghai 
num: 10011 
name: Zhang-fun 
sex: m 
age: 21 
address: 213 Shanghai Road,Beijing

代码分析

  上个程序定义了类 CStudent、类CStudentl, 其中类CStudentl继承了类CStudent。类CStudentl比基类新增了两个数据成员。基类CStudent有自己的带参构造函数,而派生类的构造函数,则只须对派生类新增的数据成员初始化,不过需要把基类的参数也给带进去。析构函数的作用是在对象撤销之前,进行必要的清理工作。当对象被删除时,系统会自动调用析构函数。析构函数比构造函数简单,没有类型,也没有参数。在派生时,派生类是不能继承基类的析构函数的,也需要通过派生类的析构函数去调用基类的析构函数。在派生类中可以根据需要定义自己的析构函数,用来对派生类中所增加的成员进行清理工作;基类的清理工作仍然由基类的析构函数负责。在执行派生类的析构函数时,系统会自动调用基类的析构函数和子对象的析构函数,对基类和子对象进行清理。