当前位置: 首页 > article >正文

C++之虚基类

虚基类(Virtual Base Class)是 C++ 中的一个特性,用于解决菱形继承问题,避免因为多重继承而导致的重复继承和冗余问题

菱形继承问题

假设有如下的类结构:

  • 一个基类 Base
  • 两个类 Derived1Derived2 继承自 Base
  • 一个类 Final 同时继承自 Derived1Derived2

这种继承关系形成了一个菱形结构:

       Base
      /    \
 Derived1  Derived2
      \    /
       Final

在这种结构中,Final 类会继承两份 Base 的副本,这可能导致以下问题:

  1. 数据冗余:Base 中的数据成员在 Final 中会有两份拷贝。
  2. 歧义:访问 Base 的成员时,编译器无法确定是从 Derived1 还是 Derived2 中继承的那一份。

虚基类的作用

虚基类通过告诉编译器:子类共享基类的一份实例,从而解决了上述问题。

示例代码

非虚基类的情况:

#include <iostream>
using namespace std;

class Base {
public:
    int value;
};

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

int main() {
    Final f;
    f.Derived1::value = 10;  // 访问 Derived1 的 Base
    f.Derived2::value = 20;  // 访问 Derived2 的 Base

    cout << f.Derived1::value << endl;  // 输出 10
    cout << f.Derived2::value << endl;  // 输出 20
}

上述代码中,Final 有两份 Base 的拷贝,导致数据冗余。

使用虚基类的情况:

#include <iostream>
using namespace std;

class Base {
public:
    int value;
};

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

int main() {
    Final f;
    f.value = 10;  // 通过共享的 Base 访问 value
    cout << f.value << endl;  // 输出 10
}

工作原理

  1. 当使用 virtual 继承时,编译器确保只有一份 Base 的实例会被所有子类共享。
  2. 无论 Derived1Derived2 如何继承 BaseFinal 类中只有一份 Base 的数据。

虚基类的特性

  1. 减少冗余: 虚基类通过共享的实例消除了多重继承中的数据冗余。
  2. 消除歧义: 对于虚基类的成员访问,不再需要显式地通过某个路径(如 Derived1::BaseDerived2::Base)来指定。
  3. 额外开销: 使用虚基类时,编译器会引入一些额外的间接访问机制,因此运行时性能可能稍有影响。

总结

  • 2个是非虚基类或1个是虚基类,内存均是分离的;
  • 2个均是虚基类,才可以共享一份内存
  • 虚拟继承不具有横向和纵向的传递性

虚基类在 C++ 中是解决菱形继承问题的关键技术。通过引入虚基类,可以使得多重继承结构更加清晰,同时避免数据冗余和访问歧义。使用虚基类时,需要权衡其额外的运行时开销与多继承的需求。


http://www.kler.cn/a/417017.html

相关文章:

  • Vue(4)
  • 采用分步式无线控制架构实现水池液位自动化管理
  • 了解“/linux-5.4.31/drivers/of/device.c”中的of_device_get_match_data()
  • 《qt easy3d中添加孔洞填充》
  • Git常用命令总结
  • 轻松理解CSS中的float浮动元素
  • 循环神经网络(RNN)简述
  • 大R玩家流失预测在休闲社交游戏中的应用
  • Android 系统之Init进程分析
  • 【Spring MVC】关于Spring MVC编程中前后端交互实现简单登录跳转和留言板实例
  • DAY139权限提升-Linux系统权限提升篇Vulnhub辅助项目SUID权限SUDO指令版本漏洞
  • Linux系统盘的空间规划与内容存放指南
  • IDEA Services窗口不显示多服务启动类,添加类型也不存在spring boot
  • 【机器学习】机器学习学习笔记 - 监督学习 - KNN线性回归岭回归 - 02
  • electron-updater软件自动检测更新 +无服务器本地测试
  • Spark优化--开发调优、资源调优、数据倾斜调优和shuffle调优等
  • 如何使用ST7789展现图片?[ESP--4]
  • 中国剩余定理——acwing
  • windows中idea选择bash作为控制台指令集,但是系统环境变量未在其中生效处理
  • Vue 2.0->3.0学习笔记(Vue 3 (一)- 创建Vue3.0工程)
  • 白鹿 Hands-on:消除冷启动——基于 Amazon Lambda SnapStart 轻松打造 Serverless Web 应用(二)
  • 《FRAPPE: fast rank approximation with explainable features for tensors》中文校对版
  • 技术分析模板
  • 【rust】前端开发中的应用与前景
  • 安卓延迟自动点击
  • pcb电路板·查错、维修心得笔记