C++ 继承与派生(二)

本文详细介绍了C++中派生类的构造函数和析构函数的工作原理与使用方法,包括简单派生类构造、有子对象的派生类构造、多层派生构造以及特殊形式的构造函数。同时阐述了派生类析构函数的调用顺序,即先执行派生类自身,然后子对象,最后基类的析构过程。

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

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

目录

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

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

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

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

5、派生类的析构函数

-----------------------------------------------------------------------------------------------------------

继承与派生的目的

继承的目的:实现代码重用。

派生的目的:当新的问题出现,原有程序无法解决(或不能完全解决)时,需要对原有程序进行改造。

派生类的构造函数

A、基类的构造函数不被继承,派生类中需要声明自己的构造函数。

B、声明构造函数时,只需要对本类中新增成员进行初始化,

调用基类构造函数对继承来的基类成员初始化。

C、派生类的构造函数需要给基类的构造函数传递参数

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

     简单派生类只有一个基类,而且只有一级派生,在派生类的数据成员中不包含基类的对象(即子对象)。

在定义派生类的构造函数时除了对自己的数据成员进行初始化外,还必须调用基类的构造函数初始化基类的数据成员。

     单一继承时的构造函数格式如下:

     派生类名::派生类名(基类所需的形参,本类成员所需的形参):基类名(基类参数表)

{    

      本类成员初始化赋值语句;  

}

派生类名后的参数表分别列出基类和派生类构造函数的形参(有类型和形参变量)。

基类参数表列出传递给基类构造函数的实参,是派生类构造函数总参数表中的参数。


用派生类构造函数的形参做基类构造函数的实参。

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

类的数据成员除了是标准类型或系统提供的类型如string外,还可以是类类型,如声明一个类时包含类型的数据成员:

Student S1;

Student是已声明过的类名,S1是该类的对象。我们称S1为子对象

派生类构造函数的任务包括:

A、对基类数据成员初始化

B、对子对象的数据成员初始化

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

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

派生类名::派生类名(总参数表):基类名(实参表),子对象名(参数表)

{   

        派生类新增成员的初始化语句;   

执行派生类构造函数的顺序是:

A、调用基类构造函数,初始化基类数据成员

B、 调用子对象构造函数,初始化子对象数据成员

C、 执行派生类构造函数,初始化派生类数据成员

 

备注:编译系统在此根据参数名(而不是参数的顺序)决定各参数表中参数之间的传递关系。如有多个子对象,要逐个列出子对象及其参数表。

案例:

class Student								 //声明基类
{
public:									//公有成员
	Student(int n, string na)				<span style="white-space:pre">	</span> //基类构造函数
	{
		num = n;
		name = na;
	}
	void display()
	{
		cout << "Num:" << num << endl;
		cout << "Name:" << name << endl;
	}
protected:								//保护成员
	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;  
	}
	void show()
	{
		cout << "this student is:" << endl;
		display();
		cout << "Age:" << age << endl;
		cout << "Address:" << addr << endl << endl;
	}
	void show_monitor()
	{
		cout << endl << "Class Monitor is:" << endl;
		monitor.display();				 //调用对象初始化值
	}
private:
	Student  monitor;
	int age;       
	string addr;   
};
int _tmain(int argc, _TCHAR* argv[])
{
	Student1 stu(1001, "八戒", 10000, "二师兄", 20, "高老庄");
	stu.show();
	stu.show_monitor();

	return 0;
}

3、多层派生时的构造函数(爷->父->孙)

一个类可以出一个派生类,派生类还可以继续派生,形成派生的层次结构。多层派生时怎么写派生类的构造函数?

如果派生类的基类也是派生类,那么每个派生类只需要负责其直接的基类数据成员的初始化

 

基类的构造函数首部:

Student(int n,string nam);

派生类Student1的构造函数首部:

Student1(int n,string nam,int a):Student(n,nam);

派生类Student2的构造函数首部:

Student2(int n,string nam,int a,int s):Student1(n,nam,a);

初始化顺序是

A、先初始化基类Student的数据成员num,nam;

B、再初始化直接派生类Student1的数据成员age;

C、最后初始化间接派生类Student2的数据成员score;

 

从结果中很清楚的说明了其构造函数和析构函数的调用顺序。

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


A、当不需要对派生类新增成员进行初始时,派生类构造函数的函数体可以为空。

B、如果在基类里没有定义构造函数,或定义了没有参数的构造函数,在定义派生类构造函 数时可以不写基类构造函

C、如果在基类和子对象的类中都没有定义带参数的构造函数,也不需要对派生类自己的数 据成员进行初始化,可以 不定义派生类构造函数。

D、如果在基类或子对象的类声明里定义了带参数的构造函数,就必须定义派生类构造函   数,并在派生类构造函数 中写出基类或子对象类的构造函数及其参数表。

E、如果在基类既定义了无参数的构造函数也定义了有参数的构造函数,在定义派生类构造 函数时,既可以包含基类 构造函数及其参数,也可以不包含基类构造函数。

 

5、派生类的析构函数

派生类不能继承基类的析构函数,注销派生类对象时,需要派生类的析构函数去调用基类的析构函数。

首先、执行派生类自己的析构函数,清理派生类新增加的成员,

其次、再调用子对象类的析构函数清理子对象,

最后、调用基类析构函数清理基类的成员。

 

    执行顺序:派生类->子对象->基类

#include "stdafx.h"
#include <iostream>
#include <string>

class C
{
private:
	std::string c;
public:
	C(){};
	C(std::string c);
	~C();
	void showC();
};

C::C(std::string c)
{
	this->c = c;
	std::cout << "构造c值为" << c << "的对象c" << std::endl;
}

C::~C()
{
	std::cout << "清理c值为" << c << "的对象c" << std::endl;
}
void C::showC()
{
	std::cout << "c=" << this->c << std::endl;
}


class D :private C
{
private:
	std::string d;
	C c;
public:
	D(std::string d, std::string c1, std::string c2);
	~D();
	void showD();
};

D::D(std::string d, std::string c1, std::string c2) :c(c2), C(c1) //参数传递给基类,也可以不写C(c1)或c(c2),那么就调<span style="white-space:pre">								</span>  //用了C类中无参构造函数
{
	this->d = d;
	std::cout << "构造对象d" << std::endl;
}

D::~D()
{
	std::cout << "清理对象d" << std::endl;
}

void D::showD()
{
	showC();
	c.showC();
	std::cout << "d=" << this->d << std::endl;
}
int main()
{
	{
		D d("ddd", "ccc1", "ccc2");
		d.showD();
	}

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值