C++深入探究不同的继承体系
目录
- 单继承
- 多继承
- 菱形继承
- 概念
- 存在的问题
- 解决方案
- 菱形虚拟继承
- 虚拟继承
- 什么是虚拟继承
- 内存层面理解虚拟继承
- 虚拟继承和普通单继承的区别
- 虚拟继承+菱形继承
声明:
本文的测试环境为Windows平台下的VS2013环境
单继承
一个子类只有一个父类。这类继承方式是最为简单的。具体可以参考继承 上篇中的例子。这里给出简单的图示即可:
多继承
一个子类有两个或两个以上的直接父类,这样的继承关系称之为多继承。
图解:
注意事项:
①在多继承的场景下,建议在继承的每一个基类名称前都加上继承方式,如果不加,可能无法达到我们的预期结果。
结论:
class修饰的类,如果不显式添加继承方式,默认是private
struct修饰的类,如果不显式添加继承方式,默认是public
②多继承的对象模型随着子类继承基类的顺序变化而变化
该如何理解上面这句话呢?
来看这两种情况:
Ⅰ、先继承Base1,再继承Base2
Ⅱ、先继承Base2,再继承Base1
菱形继承
概念
了解了上面的两种继承方式,下面我们介绍一种单继承与多继承有机结合的产品,他就是菱形继承!
它的图解如下:
存在的问题
1、存在二义性问题
最顶层基类成员在最底层子类中存在两份,如果直接通过最底层子类访问最顶层的基类成员时,会出现访问不明确问题。
2、存在数据冗余问题
我们来分析一下最底层子类的对象模型:
这里的最顶层基类为了说明问题,只有一个成员变量,但是实际中基类中的内容往往很多,数据量很大。如果不解决这个问题,那将会存在着严重的空间浪费。这是不允许的!
解决方案
解决办法:
可见,让访问明确化并不能直接解决问题!而真正能够解决问题的是采用菱形虚拟继承。这个接下来就会介绍到。
菱形虚拟继承
什么是菱形虚拟继承?
我们先不着急回答这个问题,首先我们应该搞明白什么是虚拟继承!!
虚拟继承
什么是虚拟继承
使用虚拟关键字virtual修饰的继承称之为虚拟继承
虚拟继承存在的意义就是 :为了解决菱形继承存在的二义性和数据冗余的问题
内存层面理解虚拟继承
虚拟继承和普通单继承的区别
主要有4点,具体如下:
虚拟继承+菱形继承
菱形虚拟继承实现如下:
也即:
class Base { protected: int _b; }; class Derived1 : virtual public Base { protected: int _d1; }; class Derived2 : virtual public Base { protected: int _d2; }; class D : public Derived1, public Derived2 { public: D() { } void Func() { _b = 1; _d1 = 2; _d2 = 3; } protected: int _dd; }; int main() { D d; d.Func(); return 0; }
分析执行过程及d的对象模型:
总结:菱形虚拟继承是通过让最顶层基类的成员在最底层子类中只存储一份的方式来解决的。
到此这篇关于C++深入探究不同的继承体系的文章就介绍到这了,更多相关C++继承内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!
相关推荐
-
C++的继承特性你了解吗
目录 导语: 继承作用 继承的结果 继承方式 子类构造 赋值兼容规则/向上转换/内存切片 多继承 虚拟继承 总结 导语: C++是对C语言的优化和改进,C++之所以优秀的点在于它的特性:抽象.封装.继承和多态. 本章总结继承的规则和特性,都是干货,与读者共同学习. 继承作用 代码的复用 子类继承父类,可以理解为,将父类的代码拷贝一份到子类中,达到子类可以调用父类方法的目的. 那为什么是可以理解而不是就是呢? 是因为有几个东西是不可以拷贝的,比如,父类的拷贝和析构方法,友元和静态成员. 友元关系是
-
C++详细讲解继承与虚继承实现
目录 继承的概念及定义 概念: 定义: 继承关系和访问限定符 总结 基类和派生类对象赋值转换 继承中的作用域 派生类的默认成员函数 继承与友元 继承与静态成员 复杂的菱形继承及菱形虚拟继承 虚继承原理 继承的总结 继承的概念及定义 概念: 继承机制是面向对象程序设计为了提高代码复用率的一种手段,它可以保持原类特性的基础上进行拓展,简单来说继承是类层次的复用. 接下来我们来看一个简单的继承 class Person { public: void Print() { cout<<"nam
-
C++图文并茂讲解继承
目录 一.生活中的例子 二.惊艳的继承 三.继承的意义 四.小结 一.生活中的例子 组合关系∶整体与部分的关系 下面看一个组合关系的描述代码: #include <iostream> #include <string> using namespace std; class Memory { public: Memory() { cout << "Memory()" << endl; } ~Memory() { cout <<
-
C++类继承时的构造函数
前言: 子类需要编写自己的构造函数和析构函数,需要注意的是,子类只负责对新增的成员进行初始化和扫尾编写构造和析构函数,父类成员的初始化和扫尾工作由父类的构造函数和析构函数完成. 无论何种类型的继承方式,子类都无权访问父类的所有成员,所以子类对父类的初始化需要父类的构造函数完成.此时,子类的构造函数必须提供父类构造函数所需的参数. 子类构造函数的语法如下: 子类::子类(全部参数表):父类1(父类1参数表),父类2(父类2参数表) ...对象成员1(对象成员1参数表),对象成员2(对象成
-
详解C++中单继承与多继承的使用
目录 前言 1.继承的概念和定义 (1)继承的概念 (2)继承的定义方法 (2)继承后子类的成员类型 2.基类与派生类的赋值转换 (1)派生类赋值给基类 (2)基类给派生类 3.继承中的作用域 (1)隐藏的概念 (2)例题 4.派生类的默认成员函数 (1)默认生成的成员函数 (2)自己写 5.友元与静态成员 6.多继承 (1)概念 (2)复杂的菱形继承 (3)虚继承解决菱形继承问题 (4)虚继承的原理 7.继承与组合 (1)两者区别 (2)继承与组合的区别 (3)使用情况 8.总结 前言 C++
-
C++ 超详细梳理继承的概念与使用
目录 继承的概念及定义 继承的概念 继承定义 定义格式 继承关系和访问限定符 继承基类成员访问方式的变化 基类和派生类对象赋值转换 继承中的作用域 派生类的默认成员函数 继承与友元 继承与静态成员 复杂的菱形继承及菱形虚拟继承 菱形继承 虚拟继承解决数据冗余和二义性的原理 继承的总结和反思 继承的概念及定义 继承的概念 继承机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类.继承呈现了面向对象程序设计的层次结构,体
-
C++类的继承和派生及指针安全引用
目录 一.继承和paisheng 1.继承和派生的基础概念 2.如何定义子类 3.吸收和改造父类成员.添加新成员 二.指针引用 1.指针和引用的异同 2.指针的安全隐患 一.继承和paisheng 1.继承和派生的基础概念 继承指从现有类获得其特性,派生指从已有类产生新的类.原有的类称为基类或父类,新生的类称为子类或派生类.当子类只有一个父类时称为单继承,当子类含有多个父类时称为多继承.如果基类A直接参与了派生类B的派生过程,那么A类称为直接基类:基类的基类称为间接基类. 2.如何定义子类 定义
-
C++深入探究继承的概念与使用
目录 1.概念及定义 1.1 概念 1.2 定义 2.class与struct的区别 3.赋值兼容规则 4.继承中的作用域问题 5.派生类(子类)的默认成员函数 5.1 构造函数 5.2 拷贝构造函数 5.3 赋值运算符重载 5.4 析构函数 6.基类中哪些成员被子类继承了 6.1 成员变量 6.2 成员方法 7.友元函数被继承了吗 1.概念及定义 1.1 概念 继承主要的工作就是-----共性抽取 具体地讲: ①继承机制是面向对象程序设计使代码可以复用的最重要的手段; ②允许程序员在保持原有类
-
C++ 多继承详情介绍
C++支持多继承,即允许一个类同时继承多个类. 关于多继承,一直以来争议不断,有一部分人认为多继承会带来大量的问题,为了解决这些问题会使得语言本身变得非常复杂,因此应当避免.另外一派认为多继承在某些场景下可以起到非常关键的作用,应当予以支持. 关于多重继承是好是坏,这是一个非常复杂的问题,网上历来争议不断.因此不过多阐述,感兴趣的同学可以查阅一下相关资料.仅仅从实际支持来看,目前市面上大部分的语言包括Java仅支持单继承,只有C++等少数语言支持多继承.这和C++的理念也有关,即认定不能通过减少
-
C++深入探究不同的继承体系
目录 单继承 多继承 菱形继承 概念 存在的问题 解决方案 菱形虚拟继承 虚拟继承 什么是虚拟继承 内存层面理解虚拟继承 虚拟继承和普通单继承的区别 虚拟继承+菱形继承 声明: 本文的测试环境为Windows平台下的VS2013环境 单继承 一个子类只有一个父类.这类继承方式是最为简单的.具体可以参考继承 上篇中的例子.这里给出简单的图示即可: 多继承 一个子类有两个或两个以上的直接父类,这样的继承关系称之为多继承. 图解: 注意事项: ①在多继承的场景下,建议在继承的每一个基类名称前都加上继
-
深入浅析javascript继承体系
最近做web项目,接触了jquery等框架,虽然使用方便,但是还是想学习下Javascript,今天分享下最近对js原型继承的理解,不足之处欢迎指正. 一.构造器的原型属性与原型对象 刚接触js时通常依样画瓢,用函数new一个实例,也不知道其原因,只听说js中函数即对象.原来js中没有采用Java等语言中的类继承体系,而是使用原型对象(prototype)实现继承体系,具体说是利用"构造器"实现类的功能. 首先解释下原型继承中的两个重要概念:原型属性.原型对象(实例). 就js对象系统
-
Java集合继承体系详解
Java的集合类是一种特别有用的工具,它可以用于存储数量不等的多个对象,并可以实现常用的数据结构,如栈.队列等.Java集合还可以用于板寸具有映射关系的关联数组. java集合就像是一个容器,我们可以把多个对象(实际上是对象的引用,习惯上叫对象,)保存到集合容器中.在JDK1.5以前java集合会丢失容器中所有对象的数据类型,JDK1.5以后增加了泛型,java集合可以记住容器中对象的数据类型. Java集合大致可以分为三个体系:Set List Map.所有的集合类都位于java.util包下
-
C++多重继承与虚继承分析
本文以实例形式较为全面的讲述了C++的多重继承与虚继承,是大家深入学习C++面向对象程序设计所必须要掌握的知识点,具体内容如下: 一.多重继承 我们知道,在单继承中,派生类的对象中包含了基类部分 和 派生类自定义部分.同样的,在多重继承(multiple inheritance)关系中,派生类的对象包含了每个基类的子对象和自定义成员的子对象.下面是一个多重继承关系图: class A{ /* */ }; class B{ /* */ }; class C : public A { /* */ }
-
C++中继承与多态的基础虚函数类详解
前言 本文主要给大家介绍了关于C++中继承与多态的基础虚函数类的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 虚函数类 继承中我们经常提到虚拟继承,现在我们来探究这种的虚函数,虚函数类的成员函数前面加virtual关键字,则这个成员函数称为虚函数,不要小看这个虚函数,他可以解决继承中许多棘手的问题,而对于多态那他更重要了,没有它就没有多态,所以这个知识点非常重要,以及后面介绍的虚函数表都极其重要,一定要认真的理解~ 现在开始概念虚函数就又引出一个概念,那就是重写(覆
-
关于C++中虚拟继承的一些总结分析
1.为什么要引入虚拟继承虚拟继承是多重继承中特有的概念.虚拟基类是为解决多重继承而出现的.如:类D继承自类B1.B2,而类B1.B2都继承自类A,因此在类D中两次出现类A中的变量和函数.为了节省内存空间,可以将B1.B2对A的继承定义为虚拟继承,而A就成了虚拟基类.实现的代码如下: class Aclass B1:public virtual A;class B2:public virtual A;class D:public B1,public B2; 虚拟继承在一般的应用中很少用到,所以也往
-
JavaScript基于原型链的继承
Javascript并不是一门面向对象的语言,没有提供传统的继承方式,但是它提供了一种原型继承的方式,利用自身提供的原型属性来实现继承. 原型链是JavaScript中继承的主要方法. 原型链的基本思想是:利用原型让一个引用类型继承另一个引用类型的属性和方法. 构造函数.原型和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针. 如果让原型对象等于另一个对象的实例,这样原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中
-
java设计模式—静态代理模式(聚合与继承方式对比)
一.概述 1.目标:要在Tank的move()方法做时间代理及日志代理(可以设想以后还要增加很多代理处理),且代理间的顺序可活更换 2.思路: (1)聚合:代理类聚合了被代理类,且代理类及被代理类都实现了movable接口,则可实现灵活多变,具体看代码 (2)继承:继承不够灵活,随着功能需求增多,继承体系会非常臃肿.具体看代码 二.代码 1.Movable.java 2.Tank.java 3.TankTimeProxy.java 4.TankLogProxy.java 5.Tank2Time.
随机推荐
- 使用 Iisext.vbs 列出 Web 服务扩展文件的方法
- 四种参数传递的形式——URL,超链接,js,form表单
- VBS教程:VBScript 基础-VBScript 过程
- bat、vbs、js 原生混编(一个bat可以执行vbs,js代码)
- ORA-12514及ORA-28547错误解决方案
- js关闭模态窗口刷新父页面或跳转页面
- asp.net 数据库连接池浅析
- php数组去重的函数代码
- php&java(二)
- 开启bin-log日志mysql报错的解决方法
- JS仿flash上传头像效果实现代码
- 在Mac OS上搭建Python的开发环境
- javascript事件冒泡实例分析
- 标题过长使用javascript按字节截取字符串
- PHP中使用Imagick操作PSD文件实例
- ReactNative中使用Redux架构总结
- Java版AI五子棋游戏
- 易语言实现无需加好友强制查看QQ资料卡片的方法
- 一篇文章看懂C#中的协变、逆变
- mongoDB4.0数据库的操作方法