【一天一篇CPP】派生类的构造函数和析构函数

本文详细解析了派生类构造函数的工作原理,包括构造函数的继承特性、构造顺序、多层派生及特殊形式等内容,并提供了多个实例帮助理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.基类的构造函数是不能继承的,在声明派生类时,派生类并没有把基类的构造函数继承过来,但是可以通过一种显式的声明来调用基类的构造函数。

对于析构函数,系统会自动调用基类的析构函数,详细看下面的 “3注意点”。

2.构造函数调用的例子:

#include <iostream>
#include <string>
using namespace std;

class Student{
public:
	Student (int n, string nam,char s): num (n), name (nam),sex(s){};
public:
	int num;
	string name;
	char sex;
};

class Student1: public Student
{
public:
	Student1(int n,string nam, char s,int a,string ad):Student(n,nam,s)
	{
		age = a;
		addr = ad;
		//当然也可以在上面写Student(n,nam,s),age(a),addr(ad)
	}
public:
	int age;
	string addr;
};

int main()
{
	Student1 stud(1,"C雄",'m',20,"school");
	cout << stud.num << "  " << stud.name << "  "  << stud.addr<<endl;
	return 0;
}

3.注意点:

A 派生类是先调用基类的构造函数,再构造派生类增加的成员。

B 对象释放时,基类的析构函数是自动被系统调用的,不用用户操刀。系统先调用派生类的析构函数,【然后是子对象的析构函数,】最后自动调用基类的析构函数。


4.有子对象的派生类的构造函数【子对象:对象的对象,它是类的对象,但充当另一个类的数据成员,如public: string str1;,而string本身是一个类】

如何为子对象构造呢,一个例子


#include <iostream>
#include <string>
using namespace std;


class Student{
public:
	Student (int n, string nam): num (n), name (nam){};
public:
	int num;
	string name;
};


class Student1: public Student
{
public:
	Student1(int n,string nam, int n1,string nam1, int a,string ad):Student(n,nam),monitor(n1,nam1)
	{
		age = a;
		addr = ad;
		//当然也可以在上面写Student(n,nam,s),age(a),addr(ad)
	}
public:
	Student monitor;
	int age;
	string addr;
};


int main()
{
	Student1 stud(1,"C雄",2,"B雄",20,"school");
	cout << stud.num << "  " << stud.name << "  "  << stud.addr<< "  " << stud.monitor.name<< endl;
	return 0;
}


这个例子中,派生类的构造函数包括三个部分:

A 通过基类的构造函数对基类成员进行初始化

B 通过子对象的构造函数对子对象数据成员进行初始化

C 对派生类增加的数据成员的初始化


形式总结:

派生类构造函数名( 总参数列表 ) : 基类构造函数名( 参数列表 ) , 子对象名【注意不是子对象的类名】( 参数列表 )

{派生类中新增加的数据成员的初始化,这些内容写到上一行也可以,请参照上门第一个例子}

其中若三者都写在第一行,三者的书写顺序可以改变,但是无聊如何改变,调用顺序仍然为:基类的构造函数、子对象的构造函数、新增成员的构造。


5.多层派生【派生完再派生,不是多继承的意思】和构造函数和析构函数

多层派生时的构造函数:


#include <iostream>
#include <string>
using namespace std;

class Student{
public:
	Student (int n, string nam): num (n), name (nam){};

	int num;
	string name;
};

class Student1 : public Student
{
public:
	Student1(int n,string nam,  int a):Student(n,nam)
	{
		age = a;
	}

	int age;
};

class Student2 : public Student1
{
public:
	Student2(int n, char nam[10], int a, float s): Student1(n,nam,a)
		//这里突然把string ...改为 char ...[10]了,但是因为字符指针是可以赋值给string的,所以没问题
	{
		score = s;
	}
	float score;
};


int main()
{

	Student2 std2(10,"C雄",20,80);
	cout << std2.num <<endl;
	cout << std2.name <<endl;
	cout << std2.age <<endl;
	cout << std2.score <<endl;
	return 0;
}

注意:

A 不要列出每一层派生类的构造函数,只要写出上一层派生类的构造函数即可。

B 系统会默认先构造最源头的基类,再初始化更分支的基类,最后是它自己的成员。【析构函数则相反


6.派生类的构造函数的特殊形式

A 假如派生类   没有用户定义的构造函数   或   构造函数中没有对基类的构造函数进行显式调用   ,那么意味着系统默认隐含调用基类的默认构造函数【当然这个默认构造函数可能是系统生成的,也可能是用户定义的,系统只会在用户没有定义构造函数的时候生成默认构造函数,当不能生成则派生类构造出错】。例子如下:

#include <iostream>
#include <string>
using namespace std;

class Student{
public:
	Student (int n = 50, string nam = "C雄"): num (n), name (nam){};
	

	int num;
	string name;
};

class Student1 : public Student
{
public:
	Student1( int a)
	{
		age = a;
	}

	int age;
};


int main()
{

	Student1 std1(20);
	cout << std1.num <<endl;
	cout << std1.name <<endl;
	cout << std1.age <<endl;
	return 0;
}//输出为50回车C雄回车20回车
在这个例子中若派生类自己增加的age变量不需要初始化,则可以省略它的构造函数!!

B 基类有且只有定义了带参数的构造函数【系统不会生成默认构造函数】,则在派生类中不能省略构造函数,且必须显式地调用基类的构造函数!【假如基类既有带参数的构造函数,又有没有参数的默认构造函数,则派生类的构造函数可以显式调用也可以不调用基类的构造函数】


C 以上A B 两点对基类适用,对子对象其实也适用。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值