10、多重继承、钻石继承、虚继承

2023-12-10 18:36
文章标签 继承 多重 钻石

本文主要是介绍10、多重继承、钻石继承、虚继承,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

10、多重继承、钻石继承、虚继承

  • 多重继承
    • 多重继承的内存布局
    • 多重继承的类型转换
    • 名字冲突问题
    • 名字冲突问题解决方法
  • 钻石继承(菱形继承)
    • 钻石继承问题
  • 虚继承
    • 虚继承实现原理

多重继承

多重继承的内存布局

一个类可以同时从多个基类继承实现代码

  • 子类对象内部包含多个基类子对象
  • 按照继承表的顺序依次被构造,析构的顺序则与构造严格相反
  • 各个基类子对象按照从低地址到高地址排列
    在这里插入图片描述

多重继承的类型转换

将子类对象的指针,隐式转换为它的某种基类类型指针,编译器会根据各个基类子对象在子类对象中的位置,进行适当的偏移计算。以保证指针的类型与其所指向目标对象的类型一致
在这里插入图片描述

反之,将任何一个基类类型的指针静态转换为子类类型,编译器同样会进行适当的偏移计算。

在这里插入图片描述

无论在哪个方向上,重解释类型转换(reinterpret_cast)都不进行任何偏移计算

引用的情况与指针类似,因为引用的本质就是指针

名字冲突问题

如果在子类的多个基类中,存在同名的标识符,那么任何试图通过子类对象,或在子类内部访问该名字的操作,都将引发歧义

在这里插入图片描述

名字冲突问题解决方法

  • 子类隐藏该标识符
  • 通过作用域限定操作符::显式指明所属基类

钻石继承(菱形继承)

一个子类继承自多个基类,而这些基类又源自共同的祖先这样的继承结构称为钻石继承(菱形继承)
在这里插入图片描述

钻石继承问题

公共基类子对象,在汇聚子类对象中,存在多个实例
在这里插入图片描述

虚继承

解决钻石继承的问题

  • 在继承表中使用virtual关键字
  • 虚继承可以保证
    • (1)公共虚基类子对象在汇聚子类对象中仅存一份实例
    • (2) 公共虚基类子对象被多个中间子类子对象所共享

在这里插入图片描述

虚继承实现原理

汇聚子类对象中的每个中间子类子对象都持有一个指针,通过该指针可以获取 中间子类子对象的首地址 到 公共虚基类子对象的首地址的 偏移量

在这里插入图片描述

// 虚继承 -- 钻石继承问题的解决方法
// (1)公共虚基类子对象在汇聚子类对象中仅存一份实例
// (2)公共虚基类子对象被对个中间子类对象所共享
#include <iostream>
using namespace std;
#pragma pack(1)
class A{  // 人类
public:int m_a; // 年龄
};
class X:virtual public A{   // 学生类
public:int m_x;void setAge(/* X* this */int age){this->m_a = age; // (1)this(2)X中间子类子对象(3)指针1(4)偏移量(5)this+偏移量(6)公共虚基类子对象(7)m_a}
};
class Y:virtual public A{   // 教师类
public:int m_y;int getAge(/* Y* this */){return this->m_a; // (1)this(2)Y中间子类子对象(3)指针2(4)偏移量(5)this+偏移量(6)公共虚基类子对象(7)m_a}
};
class Z:public X,public Y{ // 汇聚子类  助教类
public:int m_z;void foo(){m_a = 20;}
};int main( void ){Z z; // |X中间子类对象|Y中间子类对象|m_z|A公共基类子对象| --> |指针1 m_x|指针2 m_y|m_z|m_a|// |m_a m_x|m_a m_y|m_z|cout << "汇聚子类对象z的大小: " << sizeof(z) << endl; // 32z.setAge(35); // setAge(&z,35) --> 实参类型是Z*(子类类型指针)cout << z.getAge() << endl; // getAge(&z) --> 实参类型Z*(子类类型指针)return 0;
}

这篇关于10、多重继承、钻石继承、虚继承的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/477968

相关文章

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>

多重背包转换成0-1背包

http://acm.hdu.edu.cn/showproblem.php?pid=2191 多重背包特点: 一种物品有C个(既不是固定的1个,也不是无数个) 优化的方法: 运用神奇的二进制,进行物品拆分,转化成01背包 物品拆分,把13个相同的物品分成4组(1,2,4,6) 用这4组可以组成任意一个1~13之间的数! 原理:一个数总可以用2^

JavaSE——封装、继承和多态

1. 封装 1.1 概念      面向对象程序三大特性:封装、继承、多态 。而类和对象阶段,主要研究的就是封装特性。何为封装呢?简单来说就是套壳屏蔽细节 。     比如:对于电脑这样一个复杂的设备,提供给用户的就只是:开关机、通过键盘输入,显示器, USB 插孔等,让用户来和计算机进行交互,完成日常事务。但实际上:电脑真正工作的却是CPU 、显卡、内存等一些硬件元件。

七、Maven继承和聚合关系、及Maven的仓库及查找顺序

1.继承   2.聚合   3.Maven的仓库及查找顺序

OOP三个基本特征:封装、继承、多态

OOP三个基本特征:封装、继承、多态 C++编程之—面向对象的三个基本特征 默认分类 2008-06-28 21:17:04 阅读12 评论1字号:大中小     面向对象的三个基本特征是:封装、继承、多态。     封装 封装最好理解了。封装是面向对象的特征之一,是对象和类概念的主要特性。   封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信

c++ 类的继承详解

在 C++ 中,类的继承是一种面向对象编程(OOP)的特性,允许创建一个新的类(派生类)从一个已有的类(基类)派生。通过继承,派生类可以重用基类的属性和行为,并且可以扩展或修改这些行为。继承是一种代码重用和扩展的机制,使得派生类能够继承基类的特性并添加或修改特性。 1. 继承的基本语法 class Base {// 基类的成员};class Derived : public Base {//

C++ 第8章 继承

继承(Inheritance)是面向对象程序设计中软件重用的关键技术。 8.1 类之间的关系 一个大的应用程序,通常由多个类构成,类与类之间互相协同工作。 class Vehicle{int wheels;double weight;double loading;public:void initialize(int in_wheels, double in_weight);int get

HDU 2191 珍惜现在,感恩生活(多重背包)

OJ题目 : click here ~~ 题目分析:就一个多重背包,在输入的时候进行二进制拆分,接下来就与01背包一样处理了。关于二进制拆分,这里讲解的不错~ AC_CODE int v[1002] , c[1002];int dp[1002];int main(){int t;cin >> t;while(t--){int n ,m , i , j , a , b , d ,k

C++ 菱形继承与虚拟继承的详解与代码示例

在C++中,多重继承虽然强大,但也会带来不少问题。特别是当继承链中出现菱形继承时,容易导致基类的重复实例化。本文将深入讨论菱形继承的问题,并详细解释如何通过虚拟继承来解决它。同时,给出一个简单的代码示例,并逐步解析输出结果。 什么是菱形继承? 菱形继承是指在多重继承中,同一个基类被多个派生类继承,而这些派生类又被另一个类继承,最终形成菱形结构,如下图所示: A/ \B C\ /D