0
点赞
收藏
分享

微信扫一扫

c++的继承与派生之从入门到入坟-------集大成者

路西法阁下 2022-03-30 阅读 102

文章目录

前言

继承与派生的大杂烩

欢迎各位同学华山论剑

学习目标


提示:以下是本篇文章正文内容,下面案例可供参考

一、为什么使用继承

二、继承的工作方式

在C++中允许从一个基类或多个基类进行派生,从一个基类派生的继承称为单继承,从多个基类派生的继承称为多继承。

1.从基类中派生新类

声明格式:
class 派生类名:[派生方式] 基类名,[派生方式] 基类名
{
//派生类成员
};
如果没有标明派生方式则默认私有继承(派生方式有private public protected)

【例】
已知一个Person类,使用默认的派生方式派生一个Student类,并加入学号
(No)和班级(Class)以及printInfo()等新成员。
Person类的定义如下:
class Person
{private:
char Name[10];
int Age;
char Sex;
public:
void print()
{cout<<"Base Class Output"<endl;}
};
Student类的定义如下:
class Student:Private Person
{private: 
char Class[20];
char No[10];
public:
void printInfo()
{cout<<"Derived Class Output"<<endl;}
};

2.继承下的访问控制

在不同的继承方式下,继承的成员的访问权限也不相同。

三、派生类对象的初始化和撤销

1.单继承下的构造函数和析构函数

在派生类中的析构函数与基类析构函数的功能一样,也是在对象撤乡时进行必要的清理工作,派生类的析构函数也没有数据类型和参数。派生类析构函数,只需对新增成员进行清理和善后继承的基类和对象成员的清理和善后,由各自的析构函数来完成。
因为基类成员的初始化由基类的构造函数完成,而派生类新家成员的初始化由派生类的构造函数完成,所以派生类的构造函数和析构函数的执行顺序为:
(1).先执行基类构造函数再执行子对象构造函数最后执行派生类构造函数。
(2).先执行派生类的析构函数再执行子对象的析构函数,最后执行基类的析构函数。

【例】定义研究生(GraduateStudent)类公有继承学生(Student)类,再定义导师(Suervisor)类作为其子对象。分析GraduateStudent类的构造函数与析构函数。
程序代码如下:
#include<iostream>
using namespace std;
#include<string.h>
class Supervisor
{
	char Name[20];
	int Age;
public:
	Supervisor(const char* pName = "no name") {
		strcpy(Name, pName);
	}
	void direct() {
		cout << Name << "Directed the student" << endl;
	}
};
class Student
{
	char Name[20];
	char No[20];
public:
	Student(const char* pName = "no name", const char* stuNo = "no stuno") {
		strcpy(Name,pName);
		strcpy(No, stuNo);
	}
	void print() {
		cout << "No:" << No << endl;
		cout << "Name:" << Name << endl;
	}
};
class GraduateStudent:public Student
{
	Supervisor supervisor;
	int Grade;
public:
	GraduateStudent( char *stuName, char* stuNo, int stugrade, char* supervisor) :Student(stuName, stuNo), supervisor(supervisor)
	{
		Grade = stugrade;
	}
	void printSupervisor() {
		print;
		cout << "grade:" << Grade << endl;
		supervisor.direct();
	}
};
void main()
{
	Student stu("Li Ming", "2010112501");
	stu.print();
	GraduateStudent Gstu("Wang Hai","2010352401",20,"Advisor");
	Gstu.printSupervisor();
}

2. 多继承下的构造函数和析构函数

多继承时也涉及到基类成员,对象成员和派生类成员的初始化问题。

注意:若建立派生类对象时调用默认复制构造函数,则编译器将自动调用基类的默认复制构造函数。若编写派生类的复制构造函数,则需要为基类相应的复制构造函数传递参数。
多继承析构函数的声明方法与单继承的相同,析构函数也不能继承。派生类需要声明自己的析构函数。声明方法与普通类的析构函数相同。
提示:不需要显式的调用基类的析构函数。系统会自动隐式调用析构函数的调用次序,与构造函数相反。

三、虚基类的使用

引言
为什么c++要引虚基类的概念?
在多继承中,如果派生类的2个或多个基类具有共同的祖先基类,那么当派生类访问继承下来的公共成员时,就有可能由于同名成员的问题而引发二义性。

如下就会引起二义性
在这里插入图片描述
通过虚基类可以调整继承关系如下所示
在这里插入图片描述

1 虚基类声明一般形式:

class <派生类名 >:virtual <继承方式><基类名>注意:虚基类关键字的作用范围和继承方式与一般派生类相同,即仅对其后的基类起作用(一个基类是否为虚基是由派生类决定的).声明的虚基类以后虚基类的成员在进一步派生过程中和派生类一起维护同一个内存拷贝。**

2虚基类的初始化

【例】建立一个动物类,并派生出狼类和狗类,再构建一个狼狗类,利用虚基类实现,并分别建立各类的构造函数。
#include<iostream>
using namespace std;
/************************************************************************/
class Anmial
{
private:
	int classNo;
public:
	Anmial(int No) {
		classNo = No;
		cout << "constructing,classNo=" << classNo << endl;
	}
};
/************************************************************************/
class Wolf :virtual public Anmial
{
	int WolfNo;
public:
	Wolf(int classNo, int No) :Anmial(classNo)
	{
		WolfNo = No;
		cout << "constructing Wolf,No=" << WolfNo << endl;
	}
};
/**************************************************************************/
class Dog:virtual public Anmial
{
	int DogNo;
public:
	Dog(int classNo, int No) :Anmial(classNo) {
		DogNo = No;
		cout << "constructing Dog,No=" << DogNo << endl;
	}
};
/*************************************************************************/
class WolfDog :public Wolf, public Dog
{
	int WolfDogNo;
public:
	WolfDog(int classNo, int wolfNo, int dogNo, int No) :Anmial(classNo), Wolf(classNo, wolfNo), Dog(classNo, dogNo)
	{
		WolfDogNo = No;
		cout << "constructing WolfDog No=" << WolfDogNo << endl;
	}
};
/************************************************************************/
void main() {
	WolfDog WD(10, 101, 102, 1012);
}

结果如图
在这里插入图片描述

总结

继承和组合

继承和组合是面向对象程序设计的重要机制,在什么情况下使用类的组合又是什么情况下使用类继承呢?

类的组合

组合也是构建新类的一种手段,它主要通过包含一个已经存在的类对象的方式构建新类组合,表示类之间的"有"关系,即部分与整体的关系,其反映的是复杂的对象是由其他的对象组合而成。在构建一个类时,如果发现这个类是由其他的类对象组合而成的,且具有部分与整体的关系,这时就可以使用组合的方式构建。例如汽车有一个发动机,发动机和汽车都是独立的对象。然而汽车是一个包含发动机对象的更复杂的对象。当然,汽车不仅包含发动机,还包括车轮车门车身和音响系统。等其他对象。

类的继承

观察继承层次结构,会发现居于顶层的类往往更具有一般性,可以说是其子类共同特征的抽象。反之,沿着继承分支延伸则类变得更加的具体化,也称之为泛化-特化。根据这一特征,在使用继承创建类时,需要考虑以下因素:
(1).新类与已知类,是否具有"是"关系
(2)新类是否需要使用已知类的全部成员
(3)使用组合是否可以替代?如果能建议使用组合

类型兼容 !!!

!!!
!!!
!!!
!!!

类型兼容主要指一个公有派生类的对象,在使用上可以被当作基类的对象来使用,但是反过来使用则不行。 在具体使用过程中主要体现在:


举报

相关推荐

0 条评论