先看下面一段代码:

#include <iostream>using namespace std;class X{};
class Y:public virtual X{};
class Z:public virtual X{};
class A:public Y,public Z{};int main()
{cout << "sizeof(X) : " << sizeof(X) << endl;cout << "sizeof(Y) : " << sizeof(Y) << endl;cout << "sizeof(Z) : " << sizeof(Z) << endl;cout << "sizeof(A) : " << sizeof(A) << endl;
}

运行于VS2008上的结果是:

为什么会出现这样的结果?下面来进行分析。

先看看上述程序中类的继承关系:

我们先看类X。X类明明是空的,为什么sizeof(X) = 1呢?

原因是因为事实上X并不是空的,它有一个隐晦的1字节,那是编译器安插进去的一个char。这会是的class X的两个objects得以在内存中配置独一无二的地址。

class Y和Z的结果同样令人不解。

事实上Y和Z的大小受到三个因素的影响:

(1)语言本身所造成的额外负担。当语言支持虚基类(virtual base classes)时,就会造成一些额外负担。在子类中,这个额外负担反映在某种形式的指针身上,或者指向虚基类子对象,或者指向一个相关的表格;表格中存放的不是虚基类子对象的地址,就是其偏移量。

(2)编译器对于特殊情况所做的优化处理。虚基类子对象的1字节大小也出现在Y和Z中。传统上放在子类对象的尾端。

现在的编译器一般会对空虚基类提供特殊支持(比如VS2008)。在这个策略下,一个空虚基类被视为子类对象最开头的一部分,也就是说它并没有花费任何的额外空间。这就节省了前述的1字节。(因为既然有了成员,就不需要原本为了空类而安插的1个char)。

(3)Alignment的限制。就是字节对齐,具体可参考:字节对齐详解。在这里没有增加额外的空间。

因此,Y和Z的大小都是4字节。

下面我们讨论A的大小。

这里需要注意的是:一个虚基类子对象只会在继承类中存在一份实体,不管它在继承体系中出现了多少次!!!

A类大小由以下几点决定:

(1)被共享的X类实体,大小为1字节。

(2)Y的大小,需要减去因为虚基类X而配置的大小。4字节。

(3)A自己的大小:0字节。

(4)A字节对齐作用产生的额外空间。

结果是12字节。

注意:C++标准并不强制规定如“基类子对象的排列次序”或不同存取层级的数据成员的排列次序这种琐碎细节。也不规定虚函数和虚基类的实现细节。

【C++面向对象】类的大小以及虚继承相关推荐

  1. 类的大小,虚函数,继承

    在类中,如果什么都没有,则类占用1个字节,一旦类中有其他的占用空间成员,则这1个字节就不在计算之内,如一个类只有一个int则占用4字节而不是5字节. 如果只有成员函数,则还是只占用1个字节,因为类函数 ...

  2. 头歌C++面向对象 - 类的多态性与虚函数

    C++ 面向对象 - 类的多态性与虚函数 一.实训目的 1.掌握虚函数的基本使用. 2.掌握虚析构函数的使用. 3.掌握纯虚函数和抽象类的使用. 二.实训内容 1.人与复读机 设计人类.英语学生类和复 ...

  3. c++面试常用知识(sizeof计算类的大小,虚拟继承,重载,隐藏,覆盖)

    一. sizeof计算结构体 注:本机机器字长为64位 1.最普通的类和普通的继承 #include<iostream> using namespace std;class Parent{ ...

  4. C++ 面向对象 - 类的多态性与虚函数

    任务描述 本关任务:设计人类.英语学生类和复读机类三个类. 相关知识 为了完成完成本关任务,你需要掌握虚函数的基本使用. 多态性 在面向对象的方法中,多态性是指向不同对象发送同一个消息,不同对象在接收 ...

  5. 【Kotlin】Kotlin 面向对象 ( 类 | 成员变量 | 成员方法 | 封装 | 继承 | 多态 )

    文章目录 I . 创建简单类 ( 整型字段 ) II . 创建简单类 ( 整型字段 + 字符串字段 ) III . 类方法定义 IV . 封装 V . 继承 VI . 多态 与 抽象类 I . 创建简 ...

  6. c++虚继承和虚函数和抽象类、接口类,聚合类

    虚继承 虚继承用于解决多继承条件下的菱形继承问题(浪费存储空间.存在二义性). 底层实现原理与编译器相关,一般通过虚基类指针和虚基类表实现,每个虚继承的子类都有一个虚基类指针(占用一个指针的存储空间, ...

  7. 虚继承,虚基类以及虚继承的构造函数

    目录 一.什么是虚继承,虚基类 二.定义虚继承的基本格式 三.虚继承的构造函数 一.什么是虚继承,虚基类 虚继承:在继承定义中包含了virtual关键字的继承关系 虚基类:在虚继承体系中的通过virt ...

  8. 【C++】继承和派生、虚继承和虚基类、虚基类表和虚基类指针

    继承和派生.虚继承和虚基类.虚基类表和虚基类指针 继承和派生 继承概述 继承基本概念 派生类中的成员 继承的内容 派生类定义 派生类访问控制 对象构造和析构 对象构造和析构的调用顺序 继承中的构造和析 ...

  9. sizeof()来求一个类的大小

    基本概念 一个类的实例化对象所占空间的大小? 注意不要说类的大小,是类的对象的大小. 首先,类的大小是什么?确切的说,类只是一个类型定义,它是没有大小可言的. 用sizeof运算符对一个类型名操作,得 ...

最新文章

  1. 武汉约100所中小学将试点人工智能课,现面向社会遴选教材
  2. 教你配CISCO RIP(二)
  3. NYOJ 36 最长公共子序列 dp
  4. ubuntu16.04无法连接WiFi搜索不到网络网卡驱动
  5. 在Win10删除Ubuntu时直接删除分区后,如何删除启动项(EFI)
  6. MyBatis学习总结(21)——自定义MyBatis Generator插件
  7. 计算机继续教育笔记,《继续教育中的学习技术》读书笔记
  8. 在IT界取得成功应该知道的10件事(ZT)
  9. c语言中-(间接成员运算符)的含义
  10. java学习笔记(3.31)
  11. bbs的html代码,bbs论坛源代码
  12. js设计模式之策略模式
  13. SPDK/NVMe存储技术分析之用户态ibv_post_send()源码分析(一)
  14. python命名规则数字开头的成语_day01 Python基础
  15. HTML实现在线代码格式化、美化、加密、解密、压缩、一键转JavaScript功能工具-toolfk程序员工具网
  16. php 属猪,属猪人的流年运程
  17. Matomo API 官方接口详情
  18. 使用customRef自定义ref,解决setup中处理异步问题。
  19. ubuntu播放mp4的插件
  20. 使用JS实现博客搜索关键字高亮

热门文章

  1. 07 | 卷积神经网络:给你的模型一双可以看到世界的眼睛
  2. jQuery的实现原理
  3. linux 的 cat more less 命令有什么区别
  4. http协议建立在以下哪一个协议的基础上_HTTP协议梳理
  5. (文档挂起)打印机为什么打印失败?
  6. phpcms留言板功能的实现
  7. H5调用手机摄像头拍照,如何压缩后上传
  8. 怎么清空topic数据_20.Roscpp/Rospy:Topic_demo
  9. 素材模板源码资源下载站源码-带用户中心和VIP充值系统等
  10. oracle条件语句 如果,Oracle条件语句