c++虚基类

浅谈c++虚基类内存布局 引入虚基类的原因是为了解决三层继承,爷爷类重复存在的问题。大概操作如下:普通继承:当通过子类对象给爷爷类成员变量赋值时会出现二义性。虚继承:子类中只有一个爷爷类避免了二义性。只有对虚基类的成员变量进行处理如赋值的时候,才会用到虚基类表–取其中的值用作偏移值,来进行虚基类成员变量首地址的定位运算。 阅读详情

要介绍虚基类的作用,首先要引出多继承的概念。
多继承(Multiple Inheritance)是指从多个直接基类中产生派生类的能力,多继承的派生类继承了所有父类的成员。
多个基类的相互交织可能会带来错综复杂的设计问题,命名冲突就是不可回避的一个问题,所以虚基类的作用就是避免了多继承时产生命名冲突。

如图:
菱形继承

上图的继承方式我们称为菱形继承,我们拿此图来举例说明。
类 A 派生出类 B 和类 C,类 D 继承自类 B 和类 C,这个时候类 A 中的成员变量和成员函数继承到类 D 中变成了两份,一份来自 A–>B–>D 这条路径,另一份来自 A–>C–>D 这条路径。

所以,当我们定义D类型对象后,假如类 A 有一个成员变量 a,那么在类 D 中直接访问 a 就会产生歧义,编译器不知道它究竟来自 A –>B–>D 这条路径,还是来自 A–>C–>D 这条路径。

代码如下:


class A{
public:
    int a;
};

class B: public A{
public:
    int b;
};

class C: public A{
public:
    int c;
};

class D: public B, public C{
public:
    int d;
};
int main(){
    D x;
    x.b=10;//正确
    x.c=10;//正确
    x.d=10;//正确
    x.a=10;//错误,发生冲突

    return 0;
}

这段代码实现了上图所示的菱形继承,结果发生了错误,因为类 B 和类 C 中都有成员变量 a(从 A 类继承而来),编译器不知道选用哪一个,所以产生了歧义。
解决冲突问题有两种方法:
第一种方法,我们可以在 a 的前面指明它具体来自哪个类:
d.B::a=10; //正确
或
d.C::a=10;//正确

第二种方式:
为了解决多继承时的命名冲突和冗余数据问题,C++ 提出了虚继承,使得在派生类中只保留一份间接基类的成员。

声明虚基类的一般形式为
class 派生类名: virtual 继承方式 基类名
{
…
};

经过这样的声明后,当基类通过多条派生路径被一个派生类继承时,该派生类只继承该基类一次。

需要注意: 为了保证虚基类在派生类中只继承一次,应当在该基类的所有直接派生类中声明为虚基类。否则仍然会出现对基类的多次继承。

代码如下:

class A{
public:
    int a;
};

class B: virtual public A{  //虚继承
public:
    int b;
};

class C:virtual public A{   //虚继承
public:
    int c;
};

class D: public B, public C{
public:
    int d;
};
int main(){
    D x;
    x.b=10;//正确
    x.c=10;//正确
    x.d=10;//正确
    x.a=10;//正确

    return 0;
}

这段代码使用虚继承重新实现了上图所示的菱形继承,这样在派生类 D 中就只保留了一份成员变量 a,直接访问就不会再有歧义了。

虚继承的目的是让某个类做出声明,承诺愿意共享它的基类。其中,这个被共享的基类就称为虚基类(Virtual Base Class),本例中的 A 就是一个虚基类。在这种机制下,不论虚基类在继承体系中出现了多少次,在派生类中都只包含一份虚基类的成员。

C++中虚基类 虚基类虚基类概念虚基类是为了防止多重继承时,“孙辈”派生类派生产生对“爷爷辈”类产生多个冗余的数据而定义的概念。与正常继承自基类的区别如下面图示: A是虚基类,B1和B2虚继承自A,D继承B1和B2,D中的数据就是来自A,B1,B2中的数据而无重复冗余。 而没有使用虚继承,D中的数据就包括了两份A类的数据。虚基类例子#include <iostream> using namespace st 阅读详情

相关推荐

C++虚基类的实现机制:笔记

在《深度探索C++对象模型》里,有一个问题,也是去公司面试的时候那些技术人员常问的问题:在C++中,obj是一个类的对象,p是指向obj的指针,该类里面有个数据成员mem,请问obj.mem和p->mem在实现和效率上有什么不同。答案是:只有一种情况下才有重大差异,该情况必须满足以下3个条件:(1)、obj 是一个虚拟继承的派生类的对象(2)、mem是从虚拟基类派生下来的成员(3)、p是基类类型的

jiangnanyouzi的专栏 1万+

C++ 虚基类

C++ 虚基类. 虚基类如何解决多重继承的问题.

我是小白呀的博客 1万+

吉林大学2005级C++期末试题

2006-2007学年第1学期 2005级《C++面向对象程序设计》期末考试试题(A卷) 考试时间:2007年1月13日 班级 学号 姓名  本试卷满分100分;  请将答案写在答题纸上,写明题号,不必抄题,字迹工整、清晰;  请在答题纸和试题纸上都写上你的班级,学号和姓名,交卷时请将试题纸、答题纸和草纸 一并交上来。 一、 单选题(共10分,每题1分) 1. C++中解决命名冲突的机制是:D (A) 虚基类 (B) 虚函数 (C) 函数重载 (D) 名字空间 2. 若类A的一个对象所占的内存空间中包含虚函数表的入口地址,则: C (A) 类A不能有静态数据成员       (B) 类A中公有的成员函数一定是虚的 (C) 类A中至少有一个成员函数是虚的   (D) 类A的析构函数一定是虚的

C++虚基类

1、为什么要引入虚基类 如果一个派生类是从多个基类派生出来的,而这些基类又有一个共同的基类,则在这个派生类中访问这个共同的基类中的成员时,可能会产生二义性。 比如有以下结构 class B{ protected: int a; public: B( ){ ...} }; class B1: public B{ public: base1( ){...} }; class B2: public B{ public: B2( ){...} }; class D:public B1,pu

xdg15294969271的博客 1万+

吉林大学c++考题

吉林大学计算机科学与技术学院c++题目,2002年到2010年期末试题,部分没有答案。

VS2022+Qt6保姆级配置指南:从插件安装到项目互通全流程(附常见错误解决)

本文提供了一份详细的Visual Studio 2022与Qt6集成开发环境配置指南。从插件安装、环境搭建到项目创建与互通,涵盖了全流程操作步骤,并针对常见的配置错误和调试问题提供了实用的解决方案,帮助开发者高效构建企业级桌面应用。

nginx7reverse的博客 1203

C++对象模型(11)-- 虚基类

虚基类的介绍及其对象布局。

1191

8155平台multi-display(多屏显示)原理与配置

8155平台多屏互动原理与配置

漂流瓶の海岸 1605

C++虚基类详解

建议:能用单一继承解决的问题就不要使用多继承

Gxy_w的博客 1573

《数学建模与数学实验》第5版 线性规划 习题3.4

1. 某鸡场有1000只鸡,用动物饲料和谷物混合喂养. 2. 某工厂用A1,A2两台机床加工B1,B2,B3三种不同零件. 3. 某工厂利用两种原料甲、乙生产$A_1、A_2、A_3$三种产品. 4. 每班的护士在值班开始时向病房报到,连续工作8个小时. 5. 某工厂生产 A1 、A2 两种型号的产品 6. 有两个煤厂A,B 7. 某工厂制造三种产品,生产这三种产品需要三种资源 8. 已知某工厂计划生产1,2,3三种产品,各产品需要在ABC设备加工。...

hexiaosi_的博客 2万+

11、rsa-目标主机支持RSA密钥交换【原理扫描】的漏洞

通过将 etcd 的 TLS 密钥交换算法从 RSA 升级为 ECDHE,可实现前向保密,彻底消除 “私钥泄露导致历史流量解密” 的风险。核心步骤是通过强制启用含ECDHE的套件,并禁用 RSA 密钥交换套件,同时建议升级到 TLS 1.2+ 并优化证书类型(优先 ECDSA)。这一配置符合云原生安全最佳实践,也是 Kubernetes 等依赖 etcd 的系统推荐的安全标准。生成临时密钥的具体步骤是什么?如何验证etcd是否已成功更新为ECDH密钥交换算法?配置临时密钥交换算法可能带来哪些性能影响。

xuebo1129927648的博客 1万+

C++虚基类详解 和 多重继承

我们知道,如果一个派生类有多个直接基类,而这些直接基类又有一个共同的基类,则在最终的派生类中会保留该间接共同基类数据成员的多份同名成员。在引用这些同名的成员时,必须在派生类对象名后增加直接基类名,以避免产生二义性,使其惟一地标识一个成员,如:     c1.A::display( ) 在一个类中保留间接共同基类的多份同名成员,虽然有时是有必要的,可以在不同的数据成员中分别存放不同的数据,也

keep moving 2459

基于深度学习的树木种类识别

本文介绍了基于深度学习的树木种类识别技术。我们将通过深度学习模型和图像处理技术实现对树木的自动识别与分类。首先,我们将介绍深度学习的基本原理和相关算法。接着,我们将详细说明树木种类识别的数据准备、模型构建和训练过程。最后,我们将给出代码示例,帮助读者深入了解和实践该技术。

一键难忘的博客 2315

【C++学习笔记】虚基类(一)

1.为什么要引入虚基类? 在类的继承中,如果我们遇到这种情况: “B和C同时继承A,而B和C都被D继承” 在此时,假如A中有一个函数fun()当然同时被B和C继承,而D按理说继承了B和C,同时也应该能调用fun()函数。这一调用就有问题了,到底是要调用B中的fun()函数还是调用C中的fun()函数呢?在C++中,有两种方法实现调用: (注意:这两种方法效果是不同的) 使用作用域标识符来唯一...

小浣熊的博客 3万+

基于EB工具的TC3xx_MCAL配置开发05_ADC模块硬件Pwm触发Demo配置

基于EB工具,硬件Pwm触发ADC采集Demo配置详细介绍

initiallizer的博客 3505

机器视觉框架源码——解读5(Dock和开源UI)

本文介绍了工业软件中Dock工具面板的使用方法,主要包括三个部分:添加avalonDock引用、修改属性配置(如显示样式和背景色),以及通过MVVM命令实现布局的加载和保存。加载布局通过XmlLayoutSerializer从XML文件恢复界面状态,保存布局则将当前DockManager的布局序列化为XML文件。文章提供了代码示例和截图说明,帮助开发者快速掌握Dock面板的核心功能。

Z's Palace 401

【一天一篇CPP】C++的虚基类

一个派生类有多个直接基类,这些基类又有一个共同的基类,如图【画的很随便,就是B和C集成于A,Dji】

c熊 1107

OpenCV 基于上升距离计算边缘清晰度

OpenCV 基于上升距离计算边缘清晰度

dayuhaitang1的博客 253

C++的虚基类

/ 注意关键字virtualpublic:int b1 = 2;类B1就叫做从A虚继承,A在被虚继承的情况下被称为虚基类,注意,虚基类是有条件的,只有在被虚继承的时候才是虚基类。

b1049112625的博客 1455

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

【C++高级主题】虚基类的声明

C++ 引入了 虚基类(Virtual Base Class)机制。通过在继承时使用virtual关键字,让多个派生类共享同一个基类的实例,从而消除数据冗余和访问二义性。

byte轻骑兵的技术小窝 1924

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

C++虚基类的作用

虚基类的作用     当一个基类被声明为虚基类后,即使它成为了多继承链路上的公共基类,最后的派生类中也只有它的一个备份。例如:class CBase { };class CDerive1:virtual public CBase{ };class CDerive2:virtual public CBase{ };class CDerive12:public CDerive1,CDerive2{ }

caomiao2006的专栏 3万+

C++中的虚基类

C++中的虚基类的详解

一怀明月的博客 1320

【 C++虚基类】

虚基类是C++中解决多重继承中的菱形问题的一种机制。在多重继承时,如果一个类作为多个子类的基类出现,就会出现这个问题。通过声明虚基类,我们可以确保从多个路径继承过来的基类在内存中只有一个实例。. . . };. . . };. . . };. . . };C++中的虚基类是一种重要的语言特性。通过了解和理解虚基类的工作原理,可以更好地利用C++的面向对象特性。

武帝为此的博客 1226
上一篇: c++类的构造函数两种初始化成员方式的区别
下一篇: json for modern c++的使用
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值