C++虚继承实现机制详解:为什么它能解决菱形继承中的重复基类问题?

第一章:C++菱形继承与虚继承概述

在C++的多重继承机制中,菱形继承(Diamond Inheritance)是一种典型的继承结构,它描述了派生类通过多条路径继承同一个基类的情况。这种结构容易引发数据成员和方法的二义性问题,导致对象模型中出现重复的基类实例。

菱形继承的问题

当一个类从两个或多个具有共同基类的父类继承时,就会形成菱形结构。例如,类D继承自B和C,而B和C又都继承自A。此时,D将包含两份A的副本,造成资源浪费和访问歧义。
  • 基类成员在派生类中存在多个副本
  • 对基类成员的访问产生二义性
  • 不符合“is-a”关系的逻辑一致性

虚继承的解决方案

为解决上述问题,C++引入了虚继承(Virtual Inheritance)。通过在继承时使用virtual关键字,确保最派生类中只保留一份公共基类的实例。
// 虚继承示例
class A {
public:
    int value;
};

class B : virtual public A {};  // 虚继承A
class C : virtual public A {};  // 虚继承A
class D : public B, public C {}; // D中仅有一份A的实例
在此结构中,编译器会调整对象布局,通过指针间接访问虚基类子对象,从而保证A的成员在D中唯一存在。构造顺序也发生变化:最派生类负责调用虚基类的构造函数。
特性普通继承虚继承
基类副本数量多个唯一
访问歧义存在消除
性能开销低略高(间接访问)
虚继承是实现多重继承下正确语义的关键机制,尤其在接口类或多态设计中广泛应用。

第二章:菱形继承的问题剖析

2.1 菱形继承的典型代码结构与内存布局

菱形继承是多重继承中常见的结构,出现在一个类从两个具有共同基类的派生类中继承时。这种结构在C++中尤为典型。
代码结构示例

class A {
public:
    int x;
};

class B : public virtual A {};  // 虚继承避免重复
class C : public virtual A {};
class D : public B, public C {}; // D继承B和C,形成菱形
上述代码中,类 D 通过虚继承机制从 B 和 C 继承,而它们共同继承自 A。使用虚继承可确保 D 中仅存在一份 A 的实例。
内存布局分析
对象D的内存布局
虚基类指针(指向A) - 来自B
虚基类指针(指向A) - 来自C
B的成员(若有)
C的成员(若有)
A的成员:int x
实际布局中,编译器通过虚基类指针间接访问共享基类,避免数据冗余并维持一致性。

2.2 多重继承中基类重复实例化的现象

在多重继承中,当一个派生类通过多条路径继承同一个基类时,该基类可能被多次实例化,导致数据冗余和访问歧义。
问题示例

class Base {
public:
    int value;
};

class Derived1 : public Base {};
class Derived2 : public Base {};
class Final : public Derived1, public Derived2 {};

// 实例化
Final f;
f.Derived1::value = 10;
f.Derived2::value = 20; // 独立的副本
上述代码中,Base 类被 Derived1 和 Derived2 分别继承,最终在 Final 类中产生两个独立的 Base 子对象。这不仅浪费内存,还可能导致逻辑错误。
解决方案:虚继承
使用虚继承可确保基类仅被实例化一次:

class Derived1 : virtual public Base {};
class Derived2 : virtual public Base {};
class Final : public Derived1, public Derived2 {};
此时,Final 类中只保留一个 Base 实例,避免重复。构造过程中,Final 直接负责初始化虚基类 Base,保证唯一性与一致性。

2.3 成员访问二义性问题的实际演示

在多重继承场景下,当两个基类包含同名成员函数时,派生类将面临成员访问的二义性问题。
代码示例

class Base1 {
public:
    void display() { cout << "Base1" << endl; }
};

class Base2 {
public:
    void display() { cout << "Base2" << endl; }
};

class Derived : public Base1, public Base2 {};

int main() {
    Derived d;
    d.display(); // 编译错误:对 'display' 的调用不明确
}
上述代码中,Derived 类从 Base1 和 Base2 继承了同名函数 display(),编译器无法确定应调用哪一个,从而引发二义性错误。
解决方案分析
  • 使用作用域解析符显式指定:d.Base1::display();
  • 在派生类中重写该函数以消除歧义

2.4 菱形继承带来的对象大小膨胀分析

在多重继承中,菱形继承结构可能导致派生类对象大小异常膨胀。当两个中间基类均继承自同一个顶层基类时,若未使用虚继承,顶层基类的数据成员会被复制两份到最终派生类中。
示例代码

class Base {
public:
    int x;
};

class Derived1 : public Base {};
class Derived2 : public Base {};
class Final : public Derived1, public Derived2 {};

// sizeof(Final) = 8 (x duplicated)
上述代码中,Final 类包含两份 Base 的实例,导致 x 成员重复存储。
虚继承的优化作用
通过引入虚继承可解决该问题:

class Derived1 : virtual public Base {};
class Derived2 : virtual public Base {};
class Final : public Derived1, public Derived2 {};
// sizeof(Final) = 8 + 虚基表指针开销
此时仅保留一份 Base 子对象,但需额外维护虚基类指针(vbptr),带来轻微性能代价。
继承方式Base 实例数对象大小
非虚继承28 bytes
虚继承116 bytes(含 vbptr)

2.5 经典案例:动物-哺乳动物-宠物-老虎模型的问题再现

在面向对象建模中,常通过继承构建“动物 → 哺乳动物 → 宠物 → 老虎”这一类层次结构。然而,这种设计在语义上存在明显缺陷。
继承层级的语义冲突
老虎虽是哺乳动物,但通常不被视为宠物。将“宠物”作为“哺乳动物”的子类,再让“老虎”继承“宠物”,会导致逻辑错乱。
  • 动物(Animal):定义共性行为,如移动、进食
  • 哺乳动物(Mammal):继承 Animal,增加哺乳特性
  • 宠物(Pet):本应是角色而非生物分类
  • 老虎(Tiger):被错误归类为 Pet 的子类
代码示例与问题分析

class Animal { void move() { } }
class Mammal extends Animal { void nurse() { } }
class Pet extends Mammal { void obey() { } }
class Tiger extends Pet { void roar() { } } // 问题:老虎是宠物?
上述代码强制将老虎置于宠物继承链中,违反了现实世界语义。理想做法是使用接口或组合,例如让 Pet 成为可选行为接口,避免继承污染。

第三章:虚继承的核心机制解析

3.1 virtual继承关键字的作用与语法规则

在C++中,`virtual`继承用于解决多重继承下的菱形继承问题,避免基类成员的重复拷贝。通过声明虚继承,派生类共享同一个基类实例。
基本语法结构
class Base {
public:
    int value;
};

class Derived1 : virtual public Base {};
class Derived2 : virtual public Base {};
class Final : public Derived1, public Derived2 {};
上述代码中,`Final`对象仅包含一个`Base`子对象,`value`成员唯一。若不使用`virtual`,则`Derived1`和`Derived2`各自持有独立的`Base`副本,导致`Final`中存在二义性。
虚继承的核心特性
  • 确保公共基类在继承链中只被实例化一次
  • 由最终派生类负责初始化虚基类
  • 增加对象布局复杂度,可能引入性能开销

3.2 虚基类表(vbtable)与虚基类指针(vptr)的工作原理

在多重继承中,虚基类用于解决菱形继承带来的数据冗余问题。编译器通过虚基类表(vbtable)和虚基类指针(vptr)实现共享基类的唯一访问。
虚基类指针与表的布局
每个含有虚基类的派生类对象都会包含一个或多个指向 vbtable 的指针(vptr),这些指针通常存储在对象的起始位置附近。

class A { public: int x; };
class B : virtual public A { public: int y; };
class C : virtual public A { public: int z; };
class D : public B, public C { public: int w; };
上述代码中,D 类只拥有一个 A 的实例。B 和 C 各自包含一个指向 vbtable 的指针,vbtable 存储了从当前子对象到共享 A 实例的偏移量。
访问机制
当访问 D 对象中的 A::x 时,程序通过 vptr 查找 vbtable,再根据偏移量定位真正的 A 子对象位置,确保正确性和唯一性。
组件作用
vptr指向虚基类表,位于对象内存前部
vbtable存储到虚基类的偏移量,每类一份

3.3 虚继承下对象内存布局的重构过程

在多重继承中,若多个基类共享同一个虚基类,编译器需重构对象内存布局以避免数据冗余。此时,虚继承引入虚基类指针(vbptr),用于动态定位虚基类子对象。
内存布局调整机制
虚继承导致对象布局分为两部分:派生类自有成员与虚基类实例。中间插入vbptr,指向虚基类偏移表。
内存区域内容
Derived::a派生类成员
vbptr指向虚基类偏移量
VirtualBase::value虚基类成员
代码示例与分析

struct VirtualBase {
    int value;
};
struct Derived1 : virtual VirtualBase {};
struct Derived2 : virtual VirtualBase {};
struct Final : Derived1, Derived2 {};
上述代码中,Final仅含一个VirtualBase实例。编译器为Derived1和Derived2各插入vbptr,最终通过偏移计算统一访问路径,确保单一实例语义。

第四章:虚继承解决方案的实践验证

4.1 使用虚继承消除基类重复的编码实现

在多重继承中,若多个派生类继承同一基类,可能导致该基类在最终派生类中出现多份副本,引发二义性和资源浪费。C++ 提供虚继承机制来确保基类在整个继承链中仅存在一个实例。
虚继承的语法与应用
通过在继承时使用 virtual 关键字,声明虚基类:

class Base {
public:
    int value;
};

class DerivedA : virtual public Base {};
class DerivedB : virtual public Base {};
class Final : public DerivedA, public DerivedB {};
上述代码中,Final 类通过虚继承方式从 DerivedA 和 DerivedB 继承,确保 Base 子对象唯一。若未使用 virtual,则 Final 将包含两个 Base 副本,访问 value 时将产生二义性。
构造函数的调用顺序
虚基类的构造由最派生类直接初始化,无论中间类是否显式调用。因此,Final 的构造会优先调用 Base(),再执行 DerivedA 和 DerivedB 的构造函数。

4.2 虚继承前后对象内存布局对比实验

在C++多重继承中,菱形继承结构容易导致数据冗余和二义性。虚继承通过共享基类实例解决此问题,但会改变对象的内存布局。
普通继承的内存布局
class Base { int a; };
class Derived1 : public Base {};
class Derived2 : public Base {};
class Final : public Derived1, public Derived2 {};
此时 Final 对象包含两个 Base 子对象,共占用 8 字节(假设 int 为 4 字节),存在冗余。
虚继承后的内存布局
class Base { int a; };
class Derived1 : virtual public Base {};
class Derived2 : virtual public Base {};
class Final : public Derived1, public Derived2 {};
引入虚继承后,Final 仅包含一个共享的 Base 实例,但需额外指针指向虚基类部分(vbptr),总大小通常为 12 字节。
继承方式Base 实例数量Final 对象大小是否冗余
普通继承28 字节是
虚继承112 字节否

4.3 构造函数与初始化列表在虚继承中的调用规则

在虚继承中,最派生类负责直接调用虚基类的构造函数,无论继承层级多深。这一机制避免了菱形继承中虚基类被多次初始化的问题。
调用顺序规则
构造顺序如下:
  1. 虚基类构造函数(由最派生类通过初始化列表调用)
  2. 非虚基类构造函数
  3. 成员对象构造函数
  4. 派生类自身构造函数体
代码示例

class VirtualBase {
public:
    VirtualBase() { cout << "VirtualBase()" << endl; }
};

class DerivedA : virtual public VirtualBase {};
class DerivedB : virtual public VirtualBase {};

class MostDerived : public DerivedA, public DerivedB {
public:
    MostDerived() : VirtualBase() { // 必须显式调用
        cout << "MostDerived()" << endl;
    }
};
上述代码中,MostDerived 显式调用 VirtualBase(),确保其仅构造一次,即使路径经过多个中间类。初始化列表中的调用是强制性的,否则将使用默认构造函数。

4.4 多层虚继承下的性能开销与优化建议

在C++中,多层虚继承虽然解决了菱形继承中的数据冗余问题,但引入了显著的运行时开销。虚基类的成员访问需通过间接指针查找,导致每次访问都涉及额外的内存跳转。
虚继承的内存布局开销
虚继承会生成虚基类表(vbtable)和虚基类指针(vbptr),每个派生类对象都会包含这些额外结构,增加对象大小并影响缓存局部性。
性能对比示例

class A { public: int x; };
class B : virtual public A {};
class C : virtual public A {};
class D : public B, public C {}; // 虚继承层级
上述代码中,D 的实例需维护两个 vbptr 指向同一份 A 子对象,访问 x 需通过偏移计算,降低访问效率。
优化建议
  • 避免深度虚继承层级,优先使用组合或接口类(纯抽象类)
  • 若必须使用虚继承,尽量将虚基类设计为无数据成员的接口
  • 考虑使用 final 关键字阻止进一步继承,减少动态调度开销

第五章:总结与虚继承的适用场景分析

菱形继承问题的实际应对
在多继承结构中,当派生类通过不同路径继承同一基类时,会导致数据冗余和歧义。虚继承通过共享基类实例解决此问题。

class Base {
public:
    int value;
    Base() : value(0) {}
};

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

class Derived : public A, public B {};  // 只有一个 Base 实例
适用场景列举
  • 接口类的多重实现,如图形系统中的可绘制与可序列化特性
  • 插件架构中共享核心运行时环境
  • 需要避免状态重复且保证一致性访问的模块设计
性能与维护权衡
虚继承引入间接层,对象布局更复杂,构造函数开销增加。下表对比普通继承与虚继承的关键差异:
特性普通继承虚继承
基类实例数量多个唯一
访问速度直接偏移间接查找
内存开销低较高(vptr)
工程实践建议
优先使用组合替代多继承;若必须使用虚继承,确保基类轻量且无复杂构造逻辑。Google C++ Style Guide 明确限制虚继承仅用于接口类设计,避免在常规业务模型中滥用。
PINN驱动的3D不可压缩流场重建——从稀疏2D2C观测到完整物理场反演——含源码实现 多尺度融合策略在此发挥作用:高分辨率的2D2C数据用于约束平面内的精细结构,而低分辨率的3D3C数据提供第三维度的粗尺度信息。迁移学习架构在此发挥关键作用。这种策略在湍流封闭模型构建中尤为有效,其中RANS提供的平均流场与DNS的雷诺应力数据融合,显著提升了分离流的预测精度。在稀疏数据场景下,注意力权重根据观测数据的分布动态调整,强化数据缺失区域的物理约束,同时避免过拟合于观测点。这种机制与自适应采样的结合,实现了计算效率与重建精度的平衡,在仅保留约百分之十关键节点的情况下,仍能保持高物理一致性。 阅读详情

相关推荐

SAP 关于WPS上传文件提示“文档中不包含数据“ 和“程序正在运行中“处理办法

最近这一周经常有用户反馈,使用WPS上传文件系统报错,一直提示“程序正在运行中”,另外在导入数据的时候提示"文档中不包含数据",跟进运维过程中遇到的这两种情况,分享一下处理的办法,如果各位更好的办法也可以给我留言分享。

我小时候很黑的博客 2843

虚继承——解决菱形继承的问题以及其底层实现

在c++中我们有一种继承方式叫做菱形继承,通俗来说就是有两个类(son1,son2)都继承了同一个类(base),然后又有一个类(grandson)来继承这两个类(就是多继承的一种,个人不建议在实际开发中使用多继承)。但是这样做会带来两个问题或许这样看不是很清楚,我们上代码看看那么c++给我们提供了虚继承用来解决这种问题,只需要在son1和son2继承base时使用虚继承即可(grandson正常继承son1和son2),语法:class son1 : virtual public base {};

KingJamesX的博客 710

c语言【分糖果】2023蓝桥杯4124(枚举,递归,dfs)

但是这是不符合我们糖果刚好分完的条件的,我们应该往回退到上一层,也就是孩子6这层,然后j+1=3,孩子7分到3个第二种糖果,这也不符合我们糖果刚好分完的条件,然后就会再次回退到孩子6这里,然后j+1=4,让我们的孩子7获得5块第二种糖果,然后还是不符合糖果刚分完的条件,于是再一次退回到孩子6这里,然后就会有外循环i+1=1,j=1,孩子7分到1块第一种糖果1块第二块糖果......然后就是这样的不停地回溯,试探,直到把整棵树遍历一遍,并且记录所有的满足条件的组合。先放一下我的代码,我的代码超时啦救命!

weixin_74331419的博客 729

菱形继承和虚继承

一、单继承和多继承 单继承:一个子类只有一个直接父类时,称这个继承为单继承。 多继承:一个子类有俩个或以上的直接父类时称这个继承关系为多继承。 单继承:可以有多个父类,但是只能由一个直接父类。示意图如下: 多继承示意图如下: 菱形继承示意图如下: 菱形继承对象模型:Assistant的对象中有两份Person成员,菱形继承存在数据冗余和二义性的问题。 菱形继承举例: class person { public: string _name; }; class studen

canvasa的博客 546

Python之美——Python2与Python3多版本共存

Python多版本共存的方法Python2、Python3共存的方法python2下载及环境变量配置第一步、打开Python官网,下载Python2第二步、python2环境变量配置测试结果 Python2、Python3共存的方法 方法如下: 1.先确保不同版本解释器的python.exe所在的路径在环境变量中 2.拷贝各自的python.exe并重命名即可 步骤(理解不了下面有图示): 1、首先你需要将不同的python版本安装,且都已经将跟版本的环境变量配置好了,python3和2的下载方式

chenchen5152的博客 3944

【100%通过率】华为od机试C卷【部门人力分配】Python 实现

当前部门需要完成 N 个需求,需求用 requirements[i] 表示,requirements[i] 表示第 i 个需求的工作量大小,单位:人月。2:明显这个人力需求值有上下限的情况下【下限为requirements中的最大值,上限为requirements中的最大两个值相加(因为最多有两个需求同一个月开发)】,可以考虑使用二分法。当选择人力为6时,2个需求量为3的工作可以在1个月里完成,其他2个工作各需要1个月完成。当选择人力为5时,4个工作各需要1个月完成,一共需要4个月才能完成所有需求。

MISAYAONE的博客 2017

菱形继承问题和虚继承是如何解决二义性与数据冗余的

菱形继承问题和虚继承是如何解决二义性与数据冗余的继承是c++的三大特性之一,其中菱形继承问题是一个值得我们学习和掌握的知识点。 1.什么是菱形继承呢? 菱形继承定义为:两个子类继承同一个父类,而又有子类同时继承这两个父类。 可能这样纯粹的文字大家不能直观的理解它,下面画一幅直观图便可一目了然: 菱形继承的代码描述如下:#include<iostream> using namespac

Sakuramyb马永博的博客 1505

使用CiteSpace软件对知网文献进行关键词共现/聚类/突现分析

一、基本概念CiteSpace(引文空间)是一款专注于分析科学分析中蕴含的潜在知识的软件。它是在科学计量学、数据可视化背景下逐渐发展起来的引文可视化分析软件。通过可视化的手段,CiteSpace能够呈现科学知识的结构、规律和分布情况,并因此将这种分析得到的可视化图形称为“科学知识图谱”。二、主要功能和用途知识图谱构建:根据科学文献的引用关系,CiteSpace可以生成知识图谱,帮助研究人员更好地理解学术领域中不同文献之间的联系和演化过程。主题聚类分析。

m0_64336780的博客 1万+

解决菱形继承的方法--虚继承

菱形继承概念: ​ 两个派生类继承同一个基类 ​ 又有某个类同时继承者两个派生类 ​ 这种继承被称为菱形继承,或者钻石继承 典型的菱形继承案例: 菱形继承问题: 羊继承了动物的数据,驼同样继承了动物的数据,当草泥马使用数据时,就会产生二义性。 草泥马继承自动物的数据继承了两份,其实我们应该清楚,这份数据我们只需要一份就可以。 简单来说,就是通过多条途径重复继承了基类中的成员,就是...

yangqiang1997的博客 1163

【华为OD机试真题 Python语言】371、增强的strstr | 机试真题+思路参考+代码解析(E卷复用)

>C语言有一个库函数: char *strstr(const char *haystack,const char *needle) ,实现在字符串haystack中查找第一 次出现字符串needle的位置,如果未找到则返回null >  现要求实现一个strstr的增强函数,可以使用带可选段的字符串来模糊查询,与strstr一样返回首次查找到的字符串位置 >  可选段使用"[]"标识,表示该位置是可选段中任意一个字符即可满足匹配条件,比如"a[bc]"表示可以匹配"ab"或"ac" >&

KJ.JK 2604

YOLOv8轻量化模型瘦身术:深度解析与实战LAMP剪枝 YOLOv8(2021)

YOLOv8模型LAMP剪枝技术解析与实战 本文深入探讨了LAMP剪枝技术在YOLOv8目标检测模型中的应用。针对深度学习模型部署面临的资源限制问题,LAMP剪枝通过最小化L2失真和层自适应稀疏度分配,实现了高效模型压缩。相比传统幅度剪枝的"一刀切"方法,LAMP创新性地将剪枝建模为优化问题,定义LAMP分数来衡量权重重要性,自动确定各层最佳剪枝率。文章从理论基础出发,详细解析了LAMP的核心数学公式和算法流程,并提供了完整的YOLOv8移植实战指南,包括代码结构、剪枝步骤和微调策略。通

FJN110的博客 2422

c++-关于菱形继承&虚继承的问题总结

C++的三大特性为:封装,继承,多态。但是在继承中,存在一些使用方面的问题需要注意,接下来就总结一波。 继承: 1. 单继承–一个子类只有一个直接父类时称这个继承关系为单继承 2. 多继承–一个子类有两个或以上直接父类时称这个继承关系为多继承 例如下面这两个例子:例一(单继承):class A { public: int _a; };class B : public

2600

Amazon SES 移出沙盒完整指南 & 高通过率模板

AWS SES沙盒模式转正式模式申请指南 申请正式模式需通过AWS审核,常见被拒原因包括邮件用途不清晰、缺少退订机制或发送量不合理。人工申诉需登录AWS Support Center提交服务限额提升请求,填写详细的公司信息、邮件用途及合规措施。 高通过率申诉模板需包含: 公司信息:名称、网址及与AWS的合作情况。 邮件规范:明确类型(交易/营销)、退订链接及退信处理机制。 发送计划:合理预估发送量,确保合规。 关键点:真实信息、用途清晰、退订机制完善、发送量合理。首次被拒可修改后重新提交。

xianyinsuifeng的博客 326

每日一个C++知识点|菱形继承

本文探讨了C++中菱形继承问题及其解决方案。菱形继承指派生类同时继承两个直接基类,而这两个基类又继承自同一个间接基类,导致数据冗余、访问二义性等问题。通过虚继承机制,中间基类共享同一个间接基类实例,利用虚基类表和指针消除冗余。文章通过代码示例对比普通继承和虚继承的内存布局差异,并指出纯虚类场景下可安全使用多继承。最后强调实际开发中应优先避免多继承以减少复杂性。

weixin_46441425的博客 945

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

【面向对象编程——菱形继承与虚继承】

菱形继承与虚继承

努力搬砖ing~ 770

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

C++虚继承(理解还不到位)

无论继承的层级有多少层,只要他们之间保持着直接或者间接的继承关系,子类都可以与直接父类或者间接父类成为IsA的关系,并且能通过特定的指针对直接子类或间接子类进行相应的操作虚继承 当出现菱形继承时,一个子类可能在追溯父类时找到了同一个父类,这时参数会重复,需要虚继承来解决。 举个例子(以下来自百度百科): #include #include class CA { int k; //如果基类

sunSHINEEzy的博客 697

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

[第四天】C++继承:单继承、多继承、菱形继承和虚继承的深度解析

class 父类{};class 子类:继承方式 父类名//新增子类数据继承方式:private protected public(推荐)公共继承 保持不变,保护继承变保护,私有继承变私有,所有父类私有在子类中不可见。子类虚继承父类 子类只会保存一份公共数据。方式:在继承方式 前加virtual修饰。

m0_75045191的博客 2408

菱形继承与虚基表

参考:C++继承详解之三——菱形继承+虚继承内存对象模型详解vbptr(1) 菱形继承问题 派生类D中包含两份B基类的数据,不仅有数据冗余,还只能通过C1::m_b这样的方式来使用成员变量。 虚继承 class B {}; class C1:virtual public B {}; 虚继承会在C1类中加入一个vbptr(虚基指针)和一个vbtable(虚基表) 测试代码: #include <iostream> using namespace std; class Grand { pub

charles666_zq的博客 229

C++继承详解:从概念到菱形继承

继承是C++面向对象编程的强大特性,它支持代码重用和层次化设计。单继承简单直观,多继承功能强大但需要谨慎使用,菱形继承问题可以通过虚继承解决。合理使用继承可以创建出清晰、可维护的类层次结构。

hello world/linux 1251

C++ 虚继承:破解菱形继承的“双亲困境”

C++多继承存在菱形继承问题,导致派生类包含多个基类实例,引发二义性。虚继承通过virtual关键字解决该问题,使派生类只保留一个基类实例。虚继承的实现依赖于虚基类指针(vbptr)和虚基类表(vbtable),vbptr指向存储偏移量的vbtable,用于定位虚基类成员。在MSVC中可通过/d1reportAllClassLayout选项查看类内存布局,观察虚继承机制的具体实现。

taduanlangan的博客 466

C++虚继承

虚继承是为了解决菱形继承问题,菱形继承会产生数据冗余,并且容易产生二义性 一个菱形继承的例子 class A { public: int _a; }; // class B : public A class B : public A { public: int _b; }; // class C : public A class C : public A { public: int _c;...

Waorange的博客 390

虚继承的意义及代码

虚继承

weixin_73728113的博客 156

游戏开发之C++多继承及虚继承(C++基础)

游戏开发之C++多继承及虚继承(C++基础) 1.多继承的概念 概念:一个类(派生类)同时继承多个父类(基类)。 不推荐使用,因为多继承会带来非常严重的二义性(例如:继承的两个父类有同名的成员函数)。 多继承之菱形继承实例: class F { public: int f; void PrintF() { std::cout << __FUNCTION__ << " " << __LINE__ << ":" << f &

田螺姑娘的博客 470

C++ 继承,虚继承(内存结构)详解

本篇文章就到这里了,希望能够给你带来帮助,

raoxiaoz0425的博客 15

C++虚继承内存布局解析:从菱形继承到对象模型实践

本文深入解析C++虚继承的内存布局,从菱形继承问题出发,详细探讨虚基类指针(vbptr)和虚基类表的运作机制。通过实战代码分析对象模型,揭示虚继承与虚函数表的交互原理,并提供性能考量与使用建议,帮助开发者优化内存使用和访问效率。

weixin_29001655的博客 206

VS 调试记录

项目中有类似于这样结构的一段代码,特此记录一下调试结果。 class A { public: virtual void func() = 0; }; class B :public A { int b = 1; public: virtual void func() override { } }; class C :public A { public: virtual void

zhouguoqionghai的博客 1769
上一篇: 【稀缺资源】C++20协程内部架构解密:std::coroutine_handle的隐秘用法曝光
下一篇: 为什么顶级C++工程师都在用enum class?真相令人震惊
PixelFlow
博客等级 码龄1年 180粉丝 2207原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值