C++中的继承(三)
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++中的继承(三)相关推荐
- Django中Model继承的三种方式
Django中Model继承的三种方式 Django中Model的继承有三种: 1.抽象继承 2.多表继承 3.proxy model(代理model) 1.抽象继承 第一种抽象继承,创建一个通用父类 ...
- Python中的继承和多态
本文以生活中的基础现象为切入点,主要介绍了Python基础中继承和多态,包括单继承.多继承的语法.多态常见的 "鸭子类型". 以及如何重写父类的方法都做了详细的讲解. 一.继承的介 ...
- JavaScript学习13 JavaScript中的继承
JavaScript学习13 JavaScript中的继承 继承第一种方式:对象冒充 <script type="text/javascript">//继承第一种方式: ...
- Python中菱形继承的MRO顺序及property属性
Python中菱形继承的MRO顺序及property属性 文章目录 Python中菱形继承的MRO顺序及property属性 一.Python中菱形继承的MRO顺序 1. 单独调用父类的方法 2. 多 ...
- C++中的继承(二)
C++中的继承(二) 文章目录 C++中的继承(二) 一.派生类的默认成员函数 二.探讨派生类和基类的构造函数和析构函数真正的执行顺序 三.几个特殊的继承 一.派生类的默认成员函数 前面已经总结过类中 ...
- C++中的继承(一)
C++中的继承(一) 文章目录 C++中的继承(一) 一.继承的概念及定义 一.继承的概念及定义 1.继承的概念: 继承是面向对象程序设计中使代码复用的重要手段,它允许程序在保持原有类的结构的基础上进 ...
- JavaScript中OOP——面向对象中的继承/闭包
前 言 OOP JavaScript中OOP-->>>面向对象中的继承/闭包 1.1面向对象的概念 使用一个子类继承另一个父类,子类可以自动拥有父类的属性和方法. ...
- C++中的继承与虚函数各种概念
虚继承与一般继承 虚继承和一般的继承不同,一般的继承,在目前大多数的C++编译器实现的对象模型中,派生类对象会直接包含基类对象的字段.而虚继承的情况,派生类对象不会直接包含基类对象的字段,而是通过一个 ...
- 在java语法中继承_java中的继承
一.继承: 1.如果不使用继承,会出现以下一些问题: (1)代码重复 (2)如果要修改的话,两个类都需要修改. 2.继承体现的是一种is a 的关系.eg:Dog is a Pet;apple is ...
最新文章
- ubuntu20.04编译openjdk8
- echarts柱状图 与轴不重叠_如何让柱状图柱子不挨着坐标轴,就像图片这样
- Ant Design Landing 产品首页的设计神器
- “Node.js 包已不值得信任”
- linux sed命令_Linux sed命令用法与示例
- 微信小程序chooseImage(从本地相册选择图片或使用相机拍照)
- 【综述论文】2020年最新深度学习自然语言处理进展综述论文!!!
- HDU-1045 Fire NetFire Net 最大团
- Ubuntu安装gcc失败的那些事儿
- 企业认证CMMI都需要那些流程?
- C#网络编程技术FastSocket实战项目演练
- 改变用户在某表空间的配额不足
- FPGA学习之毛刺问题
- WGestures全局鼠标手势设置指南
- SSM整合之CRUD增删改查案例(非ajax版)
- MySQL查询优化方法
- canvas实现黑客帝国效果
- MySQL索引和B+Tree底层原理
- JAVA 时间差8个小时的问题
- 7月销量被哪吒、零跑反超,“蔚小理”怎么了?
热门文章
- ng-options track by 思考
- redis StackExchange 主备 实现 demo
- -bash:/etc/profile Permission Denied
- 80后创业故事之:兄弟散伙,创业失败(转)
- [C#] 接收和发送UDP数据
- read web.config
- 线程安全退出 VS PostMessage,SendMessage的区别
- 沟通CTBS助六和集团实现财务集中管理
- HDU多校3 - 6975 Forgiving Matching(多项式匹配字符串)
- CodeForces - 1220D Alex and Julian(思维+数论)