C++中的类继承之单继承&多继承&菱形继承
C++中的类继承之单继承&多继承&菱形继承
单继承是一般的单一继承,一个子类只 有一个直接父类时称这个继承关系为单继承。这种关系比较简单是一对一的关系:
多继承是指 一个子类有两个或以上直接父类时称这个继承关系为多继承。这种继承方式使一个子类可以继承多个父类的特性。多继承可以看作是单继承的扩展。派生类具有多个基类,派生类与每个基类之间的关系仍可看作是一个单继承。多继承下派生类的构造函数与单继承下派生类构造函数相似,它必须同时负责该派生类所有基类构造函数的调用。同时,派生类的参数个数必须包含完成所有基类初始化所需的参数个数。在子类的内存中它们是按照声明定义的顺序存放的,下面的截图将清晰看到。但是多继承存在一个问题,要想研究这个问题,我们先从单继承讲起。来看内存空间:
class Base
{
public:
Base() {
cout << "B()" << endl;
}
int b1;
};
class Derive : public Base
{
public:
Derive() {
cout << "D()" << endl;
}
int d1;
};
int main()
{
Test();
getchar();
return 0;
}
多继承的内存空间:
class Base
{
public:
Base() {
cout << "B()" << endl;
}
int b1;
};
class C
{
public:
C() {
cout << "C()" << endl;
}
int c;
};
class Derive : public Base, public C
{
public:
Derive() {
cout << "D()" << endl;
}
int d1;
};
菱形继承内存中数据分布:
class A
{
public:
A() {
cout << "A()" << endl;
}
int a;
};
class Base:public A
{
public:
Base() {
cout << "B()" << endl;
}
int b1;
};
class C: public A
{
public:
C() {
cout << "C()" << endl;
}
int c;
};
class Derive : public Base, public C
{
public:
Derive() {
cout << "D()" << endl;
}
int d1;
};在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 Base
10 {
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 A
10 {
11 public:
12 Base() {
13 cout << "B()" << endl;
14 }
15 int b1;
16 };
17 class C:virtual public A
18 {
19 public:
20 C() {
21 cout << "C()" << endl;
22 }
23 int c;
24 };
25 class Derive : virtual public Base, virtual public C
26 {
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环境下用的是偏移量,而不是图中的直接指针指向这里只是为了更直观的展示。
C++中的类继承之单继承&多继承&菱形继承的更多相关文章
- day35-2 类的三大特性---多态,以及菱形继承问题
目录 菱形继承问题 经典类 新式类 菱形继承 大招 多态与多态性 多态 多态性 多态在Python中的体现 鸭子类型(重要) 结论 菱形继承问题 经典类 没有继承object类的就是经典类,只有Pyt ...
- Learn day7 继承(单、多、菱形)\多态\魔术方法\装饰器\异常
1.继承 1.1 单继承# ### 继承 """ (1) 单继承 (2) 多继承 至少2个类,子类和父类 一个类继承另外一个类,当前类是子类 (衍生类) 被继承的这个类是 ...
- C++反汇编第五讲,认识多重继承,菱形继承的内存结构,以及反汇编中的表现形式.
C++反汇编第五讲,认识多重继承,菱形继承的内存结构,以及反汇编中的表现形式. 目录: 1.多重继承在内存中的表现形式 多重继承在汇编中的表现形式 2.菱形继承 普通的菱形继承 虚继承 汇编中的表现形 ...
- C++反汇编第四讲,认识多重继承,菱形继承的内存结构,以及反汇编中的表现形式.
目录: 1.多重继承在内存中的表现形式 多重继承在汇编中的表现形式 2.菱形继承 普通的菱形继承 虚继承 汇编中的表现形式 一丶多重继承在内存中的表现形式 高级代码: class Father1 { ...
- C++反汇编-菱形继承
学无止尽,积土成山,积水成渊-<C++反汇编与逆向分析技术揭秘> 读书笔记.马上就要出差了,回来后接着写吧. 一.概述 菱形继承是最复杂的对象结构,菱形结构会将单一继承与多重继承进行组合. ...
- C++中的类继承(4)继承种类之单继承&多继承&菱形继承
单继承是一般的单一继承,一个子类只 有一个直接父类时称这个继承关系为单继承.这种关系比较简单是一对一的关系: 多继承是指 一个子类有两个或以上直接父类时称这个继承关系为多继承.这种继承方式使一个子类可 ...
- C++继承 派生类中的内存布局(单继承、多继承、虚拟继承)
今天在网上看到了一篇写得非常好的文章,是有关c++类继承内存布局的.看了之后获益良多,现在转在我自己的博客里面,作为以后复习之用. ——谈VC++对象模型(美)简.格雷程化 译 译者前言 一个C ...
- Lua面向对象----类、继承、多继承、单例的实现
(本文转载)学习之用,侵权立删! 原文地址 http://blog.csdn.net/y_23k_bug/article/details/19965877?utm_source=tuicool&a ...
- java类为什么是单继承。类的继承,实现接口。
java中提供类与类之间提供单继承. 提供多继承会可能出现错误,如:一个类继承了两个父类,而两个父类里面都有show()方法. class Fulei1{ public void show(){ Sy ...
随机推荐
- Lucene使用与优化(转)
原文链接:http://blog.csdn.net/hongfu_/article/details/1933346 本文所使用的Lucene版本较低,年代久远,许多API可能已经变了. 1 lucen ...
- 使用ajax和window.history.pushState无刷新改变页面内容和地址栏URL (转)
在访问现在很火的google plus时,细心的用户也许会发现页面之间的点击是通过ajax异步请求的,同时页面的URL发生了了改变.并且能够很好的支持浏览器的前进和后退.不禁让人想问,是什么有这么强大 ...
- http://www.cnblogs.com/txw1958/p/alipay-f2fpay.html
一.条码支付及二维码支付介绍 1. 条码支付 条码支付是支付宝给到线下传统行业的一种收款方式.商家使用扫码枪等条码识别设备扫描用户支付宝钱包上的条码/二维码,完成收款.用户仅需出示付款码,所有收款操作 ...
- Java编程性能优化一些事儿【转】
原文出处: 陶邦仁 在JAVA程序中,性能问题的大部分原因并不在于JAVA语言,而是程序本身.养成良好的编码习惯非常重要,能够显著地提升程序性能. 1. 尽量在合适的场合使用单例 使用单例可以减轻加载 ...
- innerHTML和innerText区分
示例代码:<div id="test"> <span style="color:red">test1</span> test ...
- Word 2007 Blog Test
MAC 方法一: 引用 sudo gedit /etc/network/interfaces 将iface eth0 inet static后面添加一行 hwaddress ether 0 ...
- Python 字典 update() 方法
描述 Python 字典 update() 方法用于更新字典中的键/值对,可以修改存在的键对应的值,也可以添加新的键/值对到字典中. 用法与 Python dict() 函数相似. 语法 update ...
- __align
__align关键字指示编译器在n字节边界上对齐变量. __align是一个存储类修饰符.它不影响函数的类型. 语法 __align(n) 其中: n是对齐边界. n可以具有值1.2.4或者8. _ ...
- mysql-5.7 group commit 详解
一.mysql group commit 的官方定义: InnoDB, like any other ACID-compliant database engine, flushes the redo ...
- 简单易懂的laravel事件,这个功能非常的有用(监听事件,订阅者模式)
先说一下在什么场景会使用这个事件功能. 事情大概是这样的,需求要在用户注册的时候发一些帮助邮件给用户(原本用户在注册之后已经有发别的邮件的了,短信,IM什么的) 原来这个注册的方法也就10多行代码.但 ...