C++中的继承(三)

文章目录

  • C++中的继承(三)
    • 一、复杂菱形继承和菱形虚拟继承
    • 二、菱形继承的问题:
    • 三、解决菱形继承
    • 四、注意

一、复杂菱形继承和菱形虚拟继承

1.单继承:一个子类只有一个直接父类时称这种继承关系为单继承

2.多继承:一个子类有两个或两个以上的直接父类时,称这种继承关系为多继承。

3.菱形继承:为多继承的一种特殊情况

二、菱形继承的问题:

1.先看一段代码

class Person
{public :string _name ; // 姓名
};class Student : public Person
{protected :int _num ; //学号
};class Teacher : public Person
{protected :int _id ; // 职工编号
};class Assistant : public Student, public Teacher
{protected :string _majorCourse ; // 主修课程
};void Test ()
{// 这样会有二义性无法明确知道访问的是哪一个Assistant a ;a._name = "peter";// 需要显示指定访问哪个父类的成员可以解决二义性问题,但是数据冗余问题无法解决a.Student::_name = "xxx";a.Teacher::_name = "yyy";
}

通过上面的代码就可以发现,菱形继承的问题是容易出现二义性

即person类中有一个成员变量name,student类和teacher类都继承person类,那么student和teacher都有person类中的成员变量name

那么,Assistant类继承student和teacher类,就说明类中既有student中的name,也有teacher类中的name

此时如果在Assistant类中访问name成员变量,就会出现二义性,不知道访问那个name,此时就得加类名来访问避免二义兴。

三、解决菱形继承

1.采用菱形虚拟继承来解决菱形继承的二义性:

class Person
{public :string _name ; // 姓名
};class Student : virtual public Person
{protected :int _num ; //学号
};class Teacher : virtual public Person
{protected :int _id ; // 职工编号
};class Assistant : public Student, public Teacher
{protected :string _majorCourse ; // 主修课程
};void Test ()
{Assistant a ;a._name = "peter";
}

2.解决的原理:

用下面的代码来研究菱形虚拟继承的原理:

class A
{public:int _a;
};// class B : public A
class B : virtual public A
{public:int _b;
};// class C : public A
class C : virtual public A
{public:int _c;
};class D : public B, public C
{public:int _d;
};int main()
{D d;d.B::_a = 1;d.C::_a = 2;d._b = 3;d._c = 4;d._d = 5;return 0;
}

结合内存看一下:

菱形继承:

从上面很容易看出菱形继承的冗余

菱形虚拟继承:

结合自己画的对象模型:
菱形继承:

菱形虚拟继承:

总结:结合内存图和对象模型可以得出结论:
在派生类中,在D对象中将A对象放到派生类D的最下面,B和C取4个字节用来存放虚基表指针,虚基表指针指向虚基表,虚基表中存放偏移量,虚基表中第一个存放想对自己的偏移量,第二个存放相对_a的偏移量,通过偏移量来找到_a,这样使得A类中的数据只存一份,就解决了菱形继承的二义性

四、注意

  • 1.注意菱形虚拟继承的sizeof大小;
2.看下面代码选择A. p1 == p2 == p3
B. p1 < p2 < p3
C. p1 == p3 != p2D. p1 != p2 != p3
class Base1
{public:int _b1;
};class Base2
{public:int _b2;
};class Derive : public Base1, public Base2
{public:int _d;
};int main()
{Derive d;Base1* p1 = &d;  Base2* p2 = &d;Derive* p3 = &d;return 0;
}

答案是C

C++中的继承(三)相关推荐

  1. Django中Model继承的三种方式

    Django中Model继承的三种方式 Django中Model的继承有三种: 1.抽象继承 2.多表继承 3.proxy model(代理model) 1.抽象继承 第一种抽象继承,创建一个通用父类 ...

  2. Python中的继承和多态

    本文以生活中的基础现象为切入点,主要介绍了Python基础中继承和多态,包括单继承.多继承的语法.多态常见的 "鸭子类型". 以及如何重写父类的方法都做了详细的讲解. 一.继承的介 ...

  3. JavaScript学习13 JavaScript中的继承

    JavaScript学习13 JavaScript中的继承 继承第一种方式:对象冒充 <script type="text/javascript">//继承第一种方式: ...

  4. Python中菱形继承的MRO顺序及property属性

    Python中菱形继承的MRO顺序及property属性 文章目录 Python中菱形继承的MRO顺序及property属性 一.Python中菱形继承的MRO顺序 1. 单独调用父类的方法 2. 多 ...

  5. C++中的继承(二)

    C++中的继承(二) 文章目录 C++中的继承(二) 一.派生类的默认成员函数 二.探讨派生类和基类的构造函数和析构函数真正的执行顺序 三.几个特殊的继承 一.派生类的默认成员函数 前面已经总结过类中 ...

  6. C++中的继承(一)

    C++中的继承(一) 文章目录 C++中的继承(一) 一.继承的概念及定义 一.继承的概念及定义 1.继承的概念: 继承是面向对象程序设计中使代码复用的重要手段,它允许程序在保持原有类的结构的基础上进 ...

  7. JavaScript中OOP——面向对象中的继承/闭包

      前  言  OOP  JavaScript中OOP-->>>面向对象中的继承/闭包 1.1面向对象的概念 使用一个子类继承另一个父类,子类可以自动拥有父类的属性和方法.      ...

  8. C++中的继承与虚函数各种概念

    虚继承与一般继承 虚继承和一般的继承不同,一般的继承,在目前大多数的C++编译器实现的对象模型中,派生类对象会直接包含基类对象的字段.而虚继承的情况,派生类对象不会直接包含基类对象的字段,而是通过一个 ...

  9. 在java语法中继承_java中的继承

    一.继承: 1.如果不使用继承,会出现以下一些问题: (1)代码重复 (2)如果要修改的话,两个类都需要修改. 2.继承体现的是一种is a 的关系.eg:Dog is a Pet;apple is ...

最新文章

  1. ubuntu20.04编译openjdk8
  2. echarts柱状图 与轴不重叠_如何让柱状图柱子不挨着坐标轴,就像图片这样
  3. Ant Design Landing 产品首页的设计神器
  4. “Node.js 包已不值得信任”
  5. linux sed命令_Linux sed命令用法与示例
  6. 微信小程序chooseImage(从本地相册选择图片或使用相机拍照)
  7. 【综述论文】2020年最新深度学习自然语言处理进展综述论文!!!
  8. HDU-1045 Fire NetFire Net 最大团
  9. Ubuntu安装gcc失败的那些事儿
  10. 企业认证CMMI都需要那些流程?
  11. C#网络编程技术FastSocket实战项目演练
  12. 改变用户在某表空间的配额不足
  13. FPGA学习之毛刺问题
  14. WGestures全局鼠标手势设置指南
  15. SSM整合之CRUD增删改查案例(非ajax版)
  16. MySQL查询优化方法
  17. canvas实现黑客帝国效果
  18. MySQL索引和B+Tree底层原理
  19. JAVA 时间差8个小时的问题
  20. 7月销量被哪吒、零跑反超,“蔚小理”怎么了?

热门文章

  1. ng-options track by 思考
  2. redis StackExchange 主备 实现 demo
  3. -bash:/etc/profile Permission Denied
  4. 80后创业故事之:兄弟散伙,创业失败(转)
  5. [C#] 接收和发送UDP数据
  6. read web.config
  7. 线程安全退出 VS PostMessage,SendMessage的区别
  8. 沟通CTBS助六和集团实现财务集中管理
  9. HDU多校3 - 6975 Forgiving Matching(多项式匹配字符串)
  10. CodeForces - 1220D Alex and Julian(思维+数论)