c++继承

来源:互联网 发布:中医体质软件 编辑:程序博客网 时间:2024/06/09 14:15

一、继承的概念

继承是面向对象设计可以使代码复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能。这样产生的新类称为派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。

二、继承定义格式

 

三、继承关系

继承方式

基类的public成员

基类的protected成员

基类的private成员

继承引起的访问控制关系变化概括

Public

继承

仍为public成员

仍为protected成员

不可见

基类的非私有成员在子类的访问属性都不变

protected继承

变为protected成员

变为protected成员

不可见

基类的非私有成员都成为子类的保护成员

Private

继承

变为private成员

变为private成员

不可见

基类中的非私有成员都成为子类的私有成员

四、派生类的构成

派生类中的成员包括从基类继承过来的成员和自己增加的成员两大部分。从基类继承的成员体现了派生类从基类继承而获得的共性,而新增加的成员体现了派生类的的个性。正是这些新增加的成员体现了派生类与基类的不同。体现了不同派生类之间的区别。为了形象的地表示继承关系,采用如下图1所示来示意。在基类中包括数据成员和成员函数两部分,派生类分为两大部分:一部分是从基类继承来的成员,另一部分是在声明派生类时增加的部分。每一部分均分别包括数据成员和成员函数。

 

 

通过程序来验证这一派生类的构成:

 

程序分析:Base类里面有一个_Base_data的整型变量,Derve类里面有一个_Derve_data的整形变量并且Derve类继承了Base类。在FunTest函数中创建了派生类Derve的对象。首先对基类中的成员变量_Base_data赋值为1,其次对派生类中的成员变量_Derve_data赋值为2。通过内存窗口我们发下头四个字节里面存的是1,后四个字节里面放的是2

程序运行结果:内存窗口显示如下:

 

通过以上分析可以得出,派生类的构成即在内存中各个成员的分布方式与上图1相同。

五、总结:

1、基类的private成员在派生类中不能被访问。如果基类成员不想在类外直接被访问,但需要在派生类中能访问,就定义成protected类型。可以看出保护成员限定符是因继承才出现的。

2、public继承是一个接口继承,保持is-a原则,每个父类可用的成员对子类也可以用,因为每个子类对象也都是一个父类对象,

3、Protected/private继承是一个实现继承,基类的部分成员并非完全成为子类接口的一部分。保持has-a原则,所以非特殊情况下不会使用这两种继承关系,在绝大多数的场景下使用的都是公有继承。

4、不管是哪种集成方式,在派生类内部都可以访问基类的公有成员和保护成员,基类的私有成员存在但是在子类中不可见。

5、使用关键字class时默认的集成方式时private,使用struct时默认的继承方式时public

6、在实际运用过程中一般使用的都是public继承,极少场景下才会使用protected/private继承。

六、派生类的默认成员函数

在继承关系里面,在派生类中如果没有显示定义这六个成员函数,编译系统则会默认合成这六个成员函数。

 

1、继承关系中构造函数调用顺序

 

说明

(1)基类没有缺省构造函数,派生类必须要在初始化列表中显示给出基类名和参数列表。

(2)基类没有定义构造函数则派生类也可以不用定义,全部使用缺省构造函数。

(3)基类定义了带有形参表构造函数,派生类就一定定义构造函数。

2、继承关系中析构函数调用过程

 

 

七、继承与转换

赋值兼容规则:在public继承下

1、子类对象可以赋值给父类对象;

2、父类对象不能赋值给子类对象;

3、父类的指针/引用可以指向子类对象;

4、子类的指针/引用不能指向父类对象;

八、友元与继承

友元关系不能被被继承,也就是说基类友元不能访问子类私有和保护成员。

例:Base类里面有一个_Base_data的整型变量,并声明了一个友元函数;Derve类里面有一个_Derve_data的整形变量并且Derve类继承了Base类。在FunTest函数中创建了派生类Derve的对象b和基类的对象d

 

 

经过编译之后我们发现,派生类和基类都能使用操作符<<”。但是这并不意味者友元关系可以被继承。

在基类中的友元函数的其中一个参数是基类对象的引用,所以派生类在调用基类友元函数的时候通过赋值兼容规则对派生类的成员进行引用。

九、继承与静态成员

基类定义了static成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子类,都只有一个static成员实例;

例:

 

程序分析:如果基类里面用static修饰的成员变量在整个继承体系中有多个这样的成员的话,在测试函数中第一次和第二次输出Base::count的值都是1。如果基类里面用static修饰的成员变量在整个继承体系中只有一个这样的成员的话,在测试函数中第一次和第二次输出Base::count的值分别是:40

程序运行结果:

 

通过以上分析可以发现:基类定义了static成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子类,都只有一个static成员实例;

十、单继承&多继承&菱形继承

1、单继承

一个子类只有一个直接父类时称这个继承关系为单继承。

单继承模型:

 

单继承下的对象模型:

 

2、多继承

一个子类有两个或两个以上直接父类时称这个关系为多继承

多继承模型:

 

例:

 

 

程序分析:派生类Derve继承了基类Base1Base2,并对成员变量进行赋值。通过内存窗口可发现Derve对象模型如下图:

 

我们将派生类基类的继承顺序调换,然后观察内存窗口

 

 

通过观察内存窗口可以发现调换顺序之后的对象模型是

 

通过分析我们发现多继承的对象模型是按照基类的继承顺序由上往下分布的

3、菱形继承

继承模型:

 

对象模型:

 

说明:通过对菱形对象模型的分析可以看出菱形继承存在二义性和数据冗余的问题。

0 0
原创粉丝点击