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

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

1、虚基类的引入

我们再来复习一下“多重继承的对象布局”,假设继承的类结构是这样的:

相应的代码:

class W {
public:
    int i_w;
};
class X : public W {};
class Y : public W {};
class Z : public X, public Y {};

我们在main()函数中加入如下代码:

Z z;
cout << z.i_w << endl; //这句话编译会报错

系统提示i_w的访问不明确。为什么呢?

因为定义Z对象时,W类会被继承2次,1次是Z --> X --> W,1次是Z --> Y --> W。虚基类的提出就是为了解决这种重复继承的问题,让W类只被继承1次。

虚基类的代码如下:

class W {
public:
    int i_w;
};
class X : virtual public W {};
class Y : virtual public W {};
class Z : public X, public Y {};

2、虚基类表、虚基类表指针

我们把前面虚基类的代码修改一下:

using namespace std;

class W {
public:

};
class X : virtual public W {};
class Y : virtual public W {};
class Z : public X, public Y {};

int main()
{
    cout << sizeof(W) << endl;
    cout << sizeof(X) << endl;
    cout << sizeof(Y) << endl;
    cout << sizeof(Z) << endl;
}

输出如下:

为什么输出的结果是:1、4、4、8呢?

这里要引入2个概念:1、虚基类表 vbtable 2、虚基类表指针 vbptr。

虚基类表指针占4个字节,类X、Y各含1个虚基类表指针,类Z继承这2个虚基类表指针,所以Z对象占8个字节。

3、虚基类中的对象数据布局

为了更好地观察虚基类中的对象数据布局,我们往每个类中都增加1个成员变量。

class W {
public:
    int i_w;
};
class X : virtual public W {
public:
    int i_x;
};
class Y : virtual public W {
public:
    int i_y;
};
class Z : public X, public Y {
public:
    int i_z;
};

(1) cl /d1 reportSingleClassLayoutX ch08.cpp

虚基类表指针占4个字节,i_x占4个字节,i_w占4个字节,所以类X的对象占12个字节。

类X对象数据布局:

(2) cl /d1 reportSingleClassLayoutY ch08.cpp

类Y对象的数据布局跟类X对象类似。

(3) cl /d1 reportSingleClassLayoutZ ch08.cpp

类Z对象数据布局:

4、虚基类带虚函数时的对象布局

4.1 类W有虚函数(其他类都没虚函数)

virtual void w_h() { cout << "W::w_h()" << endl; }

这时类X的对象成员布局是这样的:

类Z的对象成员布局是这样的:

从图中可以看到,这个时候虚函数表指针vptr在子对象w的头部。

4.2 类X有虚函数(类W、X都有虚函数)

virtual void x_h() { cout << "X::x_h()" << endl; }

这时类X的对象成员布局是这样的:

类Z的对象成员布局是这样的:

4.3 类Z有虚函数 (类W、X也有虚函数)

virtual void z_h() { cout << "Z::z_h()" << endl; }

这时的对象成员布局和4.2中一样:对象Z和X共用同一个虚函数表指针。

4.4 类Z有虚函数(其他类都没虚函数)

此时Z类对象的对象布局如下:

从上面的结果看,虚基类的对象布局有如下规律:

(1)在孙子类Z的对象布局中,爷爷类(W类)的数据总是位于最后位置。

(2)父类X、Y都有一个虚基类表指针。

(3)仅爷爷类W有虚函数时,它的虚函数表指针在W类对象的头部。

(4)仅X或Y类有虚函数时,虚函数表指针就在X或W类对象的头部;在Z类对象中,虚函数表指针也位于对象的头部。

比如当Y有虚函数,其他类都没有虚函数时,类Z对象的对象布局如下:

C++ 网络库 cpp-netlib的简单使用 示例代码 (C++11, cpp-netlib版本:0.12.0) 需要链接库文件 target_link_libraries(app boost_system network-uri cppnetlib-server-parsers ) #include <network/uri.hpp> #include <nlohmann/json.hpp... 阅读详情

相关推荐

Dev-Cpp 5.11:经典C++集成开发环境安装指南

本文还有配套的精品资源,点击获取 简介:Dev-Cpp 5.11是一个开源的C++集成开发环境,针对Windows操作系统的开发者设计。安装包包含一个可执行安装程序,用户通过解压和运行它可以安装Dev-Cpp。该IDE提供了包括源代码编辑器、TDM-GCC编译器套件、项目管理工具、调试器以及诸多辅助工具在内的完整开发平台。虽然Dev-Cpp 5.11是一个稳定的老版本,但它...

weixin_36289742的博客 8210

c++中虚基类表和虚函数表的布局

本文涉及到C++中对象的内存布局知识,若无该方面基础建议先阅读haoel(陈皓)专栏的C++对象内存布局的博客: http://blog.youkuaiyun.com/haoel/article/details/3081328

castle_kao的博客 1万+

inferCNV包安装问题及解决办法

InferCNV是一个由broad研究所开发的,利用单细胞转录组数据分析肿瘤细胞拷贝数变异(CNV)的工具。基本思路是在整个基因组范围内,通过计算肿瘤细胞关于参考的“正常”细胞的相对表达,利用滑窗思想对邻近的基因相对表达,计算拷贝数。 先贴一个官方安装说明: 官方infercnv安装说明 安装infercnv包: if (!requireNamespace("BiocManager", quietly = TRUE)) install.packages("BiocManager") BiocManager:

m0_51042606的博客 6803

虚基类的基本概念

C++提供了**虚基类**使得在继承共同间接基类时只保留一份成员。

分享一些自己的学习心得体会和总结! 1万+

Tessent_StdcellLib

第二种为 Tessent Cell lib,既可用于功能仿真,也可以用于测试逻辑插入。lib包含了用于仿真的功能信息,也包含DFT cell属性。如何使用tessent工具将stdcell verilog 仿真模型转换为tessent自己的lib。运行后工具会生成一个atpg的lib文件,打开文件,找到一个带SI的DFF,只有功能描述。tessnt lib分为两种,第一种为ATBG lib,可以用于仿真;打开生成的lib文件,多了dft_cell_selection。第二部:编写attributes文件。

qq_40411444的博客 2134

手把手教你用Cadence VPWLF源和参数扫描:搞定非周期激励与gmid曲线绘制(避坑指南)

本文详细介绍了如何在Cadence Virtuoso中使用VPWLF源生成复杂非周期激励信号,并结合gmid方法进行双参数扫描优化电路设计。通过实战案例和避坑指南,帮助工程师高效解决波形生成和参数可视化难题,提升模拟电路设计效率。

weixin_29260291的博客 424

C++ 虚基类

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

我是小白呀的博客 1万+

如何用Hugo Stack主题打造极简技术博客?3个必改配置与5个高级美化技巧

本文详细解析了如何深度定制Hugo Stack主题,打造个性化技术博客。文章提供了3个必改配置与5个高级美化技巧,涵盖字体美学、布局重构、代码块视觉强化及细节打磨,帮助开发者超越基础部署,实现从功能到美学的进阶,提升博客质感与用户体验。

carrot的博客 568

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万+

从零构建:如何用MATLAB和SDR硬件搭建你的第一个OFDM卫星通信原型系统

本文详细介绍了如何利用MATLAB和SDR硬件从零构建OFDM卫星通信原型系统。通过核心组件选型、开发环境配置、OFDM算法实现到系统集成与优化的完整流程,帮助通信工程学生和DIY爱好者快速掌握软件无线电技术在卫星通信中的应用。特别推荐使用HackRF One和MATLAB工具箱实现高性价比的OFDM系统验证。

pz890123456的博客 378

保姆级教程:手把手教你用Python+Zemax仿真一个简易的Nd:YAG固体激光器谐振腔

本文提供了一份详细的Python与Zemax结合的Nd:YAG固体激光器谐振腔仿真教程。从基础理论到实战操作,涵盖晶体参数化、谐振腔设计、泵浦建模、动态仿真及热效应补偿等关键步骤,适合光学专业学生和工程师快速掌握激光器仿真技术。

weixin_30500473的博客 743

C++虚基类详解

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

Gxy_w的博客 1573

SAP 权限配置(复合角色)

复合角色创建步骤:业务场景:通常单一角色权限颗粒度划分比较细,当需要分配单一角色权限A、B(多个单一角色)给某账号用户Y时,可以先建立一个复合角色C,将A、B绑定到复合角色C中,再将角色C分配给账号Y即完成权限配置。 业务模拟: 1、PFCG创建复合角色: 2、在角色页面添加子角色 在角色分页内添加子角色,点击“菜单”分页中的“读菜单”即可导入子角色中的菜单: 3、将用户分配给...

willieyuan的博客 7087

C++虚继承性能陷阱:从对象模型看虚基类指针的开销与优化

本文深入探讨C++虚继承的性能陷阱,从对象模型角度分析虚基类指针的内存布局与访问开销。通过对比MSVC和GCC的实现差异,揭示虚继承在内存访问效率上的潜在代价,并提供针对嵌入式等内存敏感场景的优化策略,帮助开发者规避性能瓶颈。

github5actions的博客 1054

高通平台N4单路输入的720P相机预览

N4的一路720P Camera作为MIPI摄像头使用

llw21680的专栏 165

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Cpp 对象模型探索 / 含有虚基类的类的内存布局

一、栗子 class Grand { public: int i_grand_ = 8; }; class Parent1 : public virtual Grand { public: int i_parent1_ = 9; }; class Parent2 : public virtual Grand { public: int i_parent2_ = 10; }; cla...

布袋和尚 284

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

c++ 虚基类

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

xiaogou56a的专栏 895

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

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

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

keep moving 2459

虚基类及虚基类的定义使用

虚基类 在前面学过的继承过程中,不知道大家有没有想到这种情况:在多继承关系中,如果一个派生类的从两个父类那里继承过来,并且这两个父类又恰恰是从一个基类那里继承而来。那这样就麻烦了,因为你可能继承了两份一样的成员! 这就出现了所谓二义性问题,下面我们展开学习: 先给大家举一个能说明这种多继承的例子吧,笔者我想来想去,想了这么一个例子:以前呢有一个大户人家,起初呢就两口子,男主人掌权,保管着大门钥匙,后来他们有两个儿子,若干年后长大成人,男主人也老了,就把钥匙又配了两把,分别交给他的两个儿子,交由他们主持

m0_60226024的博客 4681

深入探索C++对象模型-关于对象 阅读笔记

深入探索C++对象模型-关于对象 阅读笔记 文章目录深入探索C++对象模型-关于对象 阅读笔记什么是C++对象模型C++对象模型单继承重点:多继承重点指针偏移C++多态 什么是C++对象模型 包含两方面 C++语言层面面向对象程序设计。比如相对C语言而言,支持了封装、继承、多态等性质。这些都是C++标准规定的,但是这些特性是如何实现的呢?即第二方面; 编译器底层实现模型。比如类对象的内存布局,虚函数的底层实现等。原书作者lippman参与设计了第一套C++编译器cfront。 C++对象模型 单继承

毛财胜的专栏 1349

(C++对象模型):两层结构时虚基类表内容分析

两层结构时虚基类表内容分析 虚基类表内容之5-8字节内容分析 虚基类表 一般是8字节,四个字节为一个单位。每多一个虚基类,虚基类表会多加4个字节 class Grand //爷爷类 { public: int m_grand; }; class A1 : virtual public Grand { public: int m_a1; }; class A2 : virtual public Grand { public: int m_a2; }; class C1 :public A

baidu_41388533的博客 422

《C++新经典对象模型》之第4章 数据语义学

4.1.2 成员函数参数类型的确定时机(最近碰到原则) 04.01.cpp 4.2 进程内存空间布局 最高内存地址 栈区(向下增长) 堆区(向上增长) 数据段(含BSS段) 代码段 最低内存地址进程虚拟地址空间(内存)划分: (1)栈(堆栈/栈区):局部变量等。 (2)堆(堆区):new、malloc等申请内存空间。 (3)BSS段:未初始化全局变量,初始化为0的全局变量。 (4)数据段:已初始化的全局变量,包含BSS段。 (5)代码段:存放程序执行代码。Linux上列出可执行文件中全局变量等存放位置的

yxqq378287007的博客 920

【CPP11?】结合CPP发展历史来理解CPP11

由C到CPP的大概历史是如何的?CPP是一门怎样的语言?想必浏览本文将会对此有一些初步的认识,本文是结合历史来介绍CPP的发展历程的。

BinaryWiker的博客 1262

深度探索C++对象模型

c++对象模型语言中直接支持面向对象程序设计的部分对于各种支持的底层实现机制说白了是介绍编译器是如何支持、实现C++的面向对象机制的。如,继承、虚函数、指向class members的指针等等,编译器是如何实现的。本书C++语法基于C++95本书出版自2001年,虽然书中用到的标准早已盖棺定论,cfront编译器也早已过时,当时来看一些无法确定的标准、难以实现的技术、功能也早已实现,但是对C++对象模型的某些实现方式依然沿用至今。这本书依然不过时。

surfaceyan的博客 1825
上一篇: C++对象模型(10)-- 虚函数2
下一篇: C++对象模型(12)-- 构造函数语义学:构造函数
老蔡编程
博客等级 码龄23年 48粉丝 75原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值