1小时深入c++面向对象编程

四、继承性和派生性

4.1 基类和派生类

基类(父类):已存在的用来派生新类的类

派生类(子类):由已存在的类派生出的新类

图4-1 派生类的构成

4.2 单继承与多继承

单继承:从一个基类派生的继承

多继承:从多个基类派生的继承

图4-2 单继承与多继承

4.2.1 单继承

格式:

图4-3 单继承

4.2.3 继承方式

public:公有继承

private:私有继承

protected:保护继承

作用:控制基类中声明的成员在多大的范围内能被派生类的用户访问

补充:对象只能访问类中pbulic(公有)成员,不能访问private和protected成员

缺省继承方式为private

4.2.3 继承对基类成员的访问能力

公有继承:1派生类成员函数可以访问基类非私有成员

2派生类的派生类成员函数可以访问基类非私有成员

3类的对象可以访问基类的公有成员

私有继承:1派生类成员函数可以访问基类非私有成员

2派生类的派生类成员函数无法访问基类所有成员

3类的对象无法访问基类的所有成员

保护继承:1派生类成员函数可以访问基类非私有成员

2派生类的派生类成员函数可以访问基类非私有成员

3类的对象无法访问基类的所有成员

4.2.4 总结

图4-4 继承对基类成员访问权限

4.2.5 示例

图4-5 继承的访问能力

图4-6 继承的访问能力(续)

图4-7 继承的访问能力(续)

4.2.6 基类与派生类的关系

1派生类是基类的具体化基类是对若干个派生类的抽象,而派生类是基类的具体化;基类抽取了它的派生类的公共特征,而派生类通过增加行为将抽象类变为某种有用的类型

2派生类是基类定义的延续

3派生类是基类的组合派生类将其自身与基类区别开来的方法是添加数据成员和成员函数

4.2.7 派生类构造函数调用顺序

基类的构造函数>>子对象的构造函数>>派生类构造函数体

4.2.8 派生类析构函数

析构函数不能被继承

执行派生类的析构函数时,基类的析构函数也将被调用

析构函数的执行顺序与构造函数严格相反

4.2.9 示例

图4-8 派生类构造函数调用顺序

4.2.10 派生类构造函数使用中应注意的问题

派生类构造函数的定义中可以省略对基类构造函数的调用,其条件是在基类中必须有缺省的构造函数或者根本没有定义任何构造函数(编译器会自动生成缺省构造函数)

当基类的构造函数使用一个或多个参数时,派生类必须定义构造函数,提供将参数传递给基类构造函数的途径(设基类数据成员为m个,派生类数据成员为n个,派生类的参数个数为x,则:0≤x≤m+n)

图4-9 派生类构造函数参数问题

4.2.10 多继承

格式:

图4-10 多继承

图4-11 多继承构造函数格式

派生类构造函数负责所有基类构造函数的调用

派生类构造函数执行顺序:执行所有基类的构造函数>>执行所有子对象的构造函数>>执行派生类构造函数体

处于同一层次的各基类构造函数的执行顺序取决于定义派生类时所指定的各基类顺序,与派生类构造函数中所定义的成员初始化列表中的各项顺序无关

4.2.11 示例

图4-12 多继承构造函数调用顺序

4.3 二义性问题

原因:在多继承情况下,造成的对基类中某个成员的访问出现的不唯一的情况

4.3.1 成员函数二义性

图4-13 成员函数二义性

解决方法:1区别出是类A或类B的f函数,c1.A::f()或c1.B::f()

                2在类中定义同名函数f

当一个派生类从多个基类派生,而这些基类又有一个共同的基类,则对该基类中说明的成员进行访问时,可能会出现二义性

4.3.2 成员变量二义性

图4-14 成员变量二义性

解决办法:1区别出是通过类B1或类B2调用类A的a,c1.B1::a或c1.B2::a

                2虚基类

4.3.3 解决办法

利用成员名限定法消除二义性

在类中定义一个同名成员

虚基类

4.3.4 特殊说明

一个类不能从同一个类中直接继承一次以上

二义性检查在访问控制和类型检查之前进行,访问控制和类型检查不能解决二义性问题

4.3.5 示例

图4-15 二义性示例

4.4 虚基类

格式:virtual<继承方式> <基类名>

说明:关键字virtual与关键字public或private的相对位置无关,但必须位于虚基类名之前,且virtual只对紧随其后的基类名起作用

例如:class D:virtualpublic A,private B,virutalpublic C 其中,类A和类C是虚基类,而类B是非虚基类

4.4.1 虚基类与非虚基类的存储结构

图4-16 虚基类与非虚基类存储结构

4.4.2 虚基类的构造函数

派生类中只有一个虚基类子对象

虚基类构造函数必须只被调用一次,目的是要保证虚基类子对象只被初始化一次

最派生类:继承结构中建立对象时所指定的类

虚基类子对象由最派生类的构造函数通过调用虚基类的构造函数进行初始化

在一个成员初始化列表中出现对虚基类和对非虚基类构造函数的调用时,虚基类的构造函数先于非虚基类的构造函数的执行

最派生类的构造函数的成员初始化列表中必须给出对虚基类的构造函数的调用;如果未列出,则相应的虚基类必须有缺省构造函数

图4-17 虚基类的构造函数

4.4.3 示例

图4-18 虚基类与非虚基类

4.4.4 小结

图4-19 初始化顺序

传送门:1小时精通c++面向对象编程

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Python研发

javascript作用域

javascript的作用域一直以来是前端开发中比较难理解的知识点,对于javascript的作用域主要记住几句话.

10520
来自专栏北京马哥教育

Python Re 模块最全解读: 11703 字帮你彻底掌握

re模块下的函数 compile(pattern):创建模式对象 import re pat=re.compile('A') m=pat.search('CBA...

347100
来自专栏待你如初见

Day07

有了继承以后,我们定义一个类的时候,可以在一个已经存在的类的基础上,还可以定义自己的新成员

10610
来自专栏前端知识分享

第202天:js---原型与原型链终极详解

JavaScript 中,万物皆对象!但对象也是有区别的。分为普通对象和函数对象,Object 、Function 是 JS 自带的函数对象。下面举例说明

21420
来自专栏土豆专栏

Java面试之字符串

JVM为了提高性能和减少内存的开销,在实例化字符串的时候进行了一些优化:使用字符串常量池。每当我们创建字符串常量的时候,JVM会首先检查字符串常量池,如果该字符...

18810
来自专栏Hongten

算法入门-二分查找算法

2.如果中间值小于被查找的值,则选择中间值右边的数组,重复1,直到发现与被查找的值相等的数组元素或返回某个值,表示被查找的值在数组中不存在。

26120
来自专栏函数式编程语言及工具

泛函编程(9)-异常处理-Option

     Option是一种新的数据类型。形象的来描述:Option就是一种特殊的List,都是把数据放在一个管子里;然后在管子内部对数据进行各种操作。所以Op...

20160
来自专栏古时的风筝

Python----reduce原来是这样用的

官方解释: Apply function of two arguments cumulatively to the items of iterable, fro...

25360
来自专栏工科狗和生物喵

【计算机本科补全计划】Java学习笔记(三) 数据类型

正文之前 Java的面向对象特性太明显了。先开篇告诉你我们的对象是啥意思,然后直截了当的告诉你,每个文件都是一个类。也就是说每个文件都可以给你传出来一种对象,然...

36140
来自专栏文武兼修ing——机器学习与IC设计

JavaScript入门笔记(5)函数

函数 函数就是最基本的一种代码抽象的方式 函数的声明与调用 JavaScript中声明函数的方法有两种 声明一个有名称的函数,使用类似C语言的functi...

36180

扫码关注云+社区

领取腾讯云代金券