博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++中的类继承(4)继承种类之单继承&多继承&菱形继承
阅读量:4695 次
发布时间:2019-06-09

本文共 2625 字,大约阅读时间需要 8 分钟。

单继承是一般的单一继承,一个子类只 有一个直接父类时称这个继承关系为单继承。这种关系比较简单是一对一的关系:

 

多继承是指 一个子类有两个或以上直接父类时称这个继承关系为多继承。这种继承方式使一个子类可以继承多个父类的特性。多继承可以看作是单继承的扩展。具有多个基类,与每个基类之间的关系仍可看作是一个单继承。多继承下派生类的构造函数与单继承下派生类构造函数相似,它必须同时负责该派生类所有基类构造函数的调用。同时,派生类的参数个数必须包含完成所有基类初始化所需的参数个数。在子类的内存中它们是按照声明定义的顺序存放的,下面的截图将清晰看到。

菱形继承也叫钻石继承

 

但是多继承存在一个问题,要想研究这个问题,我们先从单继承讲起。来看内存空间:

1 class Base 2 { 3 public: 4 Base() { 5 cout << "B()" << endl; 6 } 7 int b1; 8 }; 9 class Derive : public Base10 {11 public:12 Derive() {13 cout << "D()" << endl;14 }15 int d1; 16 };17 int main()18 {19 Test();20 getchar();21 return 0;22 }

多继承的内存空间:

1 class Base 2 { 3 public: 4 Base() { 5 cout << "B()" << endl; 6 } 7 int b1; 8 }; 9 class C10 {11 public:12 C() {13 cout << "C()" << endl;14 }15 int c;16 };17 class Derive : public Base, public C18 {19 public:20 Derive() {21 cout << "D()" << endl;22 }23 int d1; 24 };

菱形继承内存中数据分布:

1 class A 2 { 3 public: 4 A() { 5 cout << "A()" << endl; 6 } 7 int a; 8 }; 9 class Base:public A10 {11 public:12 Base() {13 cout << "B()" << endl;14 }15 int b1;16 };17 class C: public A18 {19 public:20 C() {21 cout << "C()" << endl;22 }23 int c;24 };25 class Derive : public Base, public C26 {27 public:28 Derive() {29 cout << "D()" << endl;30 }31 int d1; 32 };

在A类中初始化int a=4则可清楚的看到菱形继承中内存分布所以子类Derive中有两份A类中的数据成员,这造成了访问二义性和数据冗余的问题这就是我前面说的多继承存在的问题。可以这样访问

1 tmp.C::a=4;2 tmp.Base::a=5;

什么是对象模型

有两个概念可以解释C++对象模型:

1、语言中直接支持面向对象程序设计的部分。

2、对于各种支持的底层实现机制。

还有另外一个方法解决这个问题,我们要用到一种新的继承方法:虚继承--解决菱形继承的二义性和数据冗余的问题。看下面这段代码:

1 class Base 2 { 3 public: 4     Base() { 5         cout << "B()" << endl; 6     } 7     int b1; 8 }; 9 class Derive : virtual public Base10 {11 public:12     Derive() {13         cout << "D()" << endl;14     }15     int d1; 16 };17 void Test()18 {19     Derive tmp;20     tmp.d1 = 1;21     tmp.b1 = 2;23 }24 int main()25 {26     Test();27     getchar();28     return 0;29 }

虚拟继承的关键字---virtual

1 class A 2 { 3 public: 4     A() { 5         cout << "A()" << endl; 6     } 7     int a ; 8 }; 9 class Base : virtual public A10 {11 public:12     Base() {13         cout << "B()" << endl;14     }15     int b1;16 };17 class C:virtual public A18 { 19 public:20     C() {21         cout << "C()" << endl;22     }23     int c;24 };25 class Derive : virtual public Base, virtual public C26 {27 public:28     Derive() {29         cout << "D()" << endl;30     }31     int d1; 32 };33 void Test()34 {35     Derive tmp;36     tmp.d1 = 1;37     tmp.b1 = 2;38     tmp.c = 3;39     tmp.a = 4;40 }41 int main()42 {43     Test();44     getchar();45     return 0;46 }

菱形虚拟继承的对象模型解决二义性问题在vs环境下用的是偏移量,而不是图中的直接指针指向这里只是为了更直观的展示。

转载于:https://www.cnblogs.com/tangshiguang/p/6735317.html

你可能感兴趣的文章
查询SQL数据库名和表字段名
查看>>
拨号助手pppd插件--用openwrt路由共享上网
查看>>
浅谈高并发的理解
查看>>
强大的拖拽插件
查看>>
JavaScript基础知识(DOM)
查看>>
java Socket 学习
查看>>
composer install 出现“Please provide a valid cache path”
查看>>
腻子脚本
查看>>
[bbk4397] 第1集 - 第一章 AMS介绍
查看>>
hdu1003 最大连续子序和
查看>>
sql 时期格式整理
查看>>
UWP开发-获取设备唯一ID
查看>>
js for循环删除两个数组相同元素
查看>>
XPage 高级技术 -- 动态创建控件
查看>>
http与https的区别
查看>>
GLSL版本的区别和对比
查看>>
android 全屏视频播放(SurfaceView + MediaPlayer)
查看>>
openstack-ocata-身份验证2
查看>>
查找 与 排序 总结
查看>>
Scrapy学习笔记(5)-CrawlSpider+sqlalchemy实战
查看>>