【C++面向对象】类的大小以及虚继承
先看下面一段代码:
#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个字节就不在计算之内,如一个类只有一个int则占用4字节而不是5字节. 如果只有成员函数,则还是只占用1个字节,因为类函数 ...
- 头歌C++面向对象 - 类的多态性与虚函数
C++ 面向对象 - 类的多态性与虚函数 一.实训目的 1.掌握虚函数的基本使用. 2.掌握虚析构函数的使用. 3.掌握纯虚函数和抽象类的使用. 二.实训内容 1.人与复读机 设计人类.英语学生类和复 ...
- c++面试常用知识(sizeof计算类的大小,虚拟继承,重载,隐藏,覆盖)
一. sizeof计算结构体 注:本机机器字长为64位 1.最普通的类和普通的继承 #include<iostream> using namespace std;class Parent{ ...
- C++ 面向对象 - 类的多态性与虚函数
任务描述 本关任务:设计人类.英语学生类和复读机类三个类. 相关知识 为了完成完成本关任务,你需要掌握虚函数的基本使用. 多态性 在面向对象的方法中,多态性是指向不同对象发送同一个消息,不同对象在接收 ...
- 【Kotlin】Kotlin 面向对象 ( 类 | 成员变量 | 成员方法 | 封装 | 继承 | 多态 )
文章目录 I . 创建简单类 ( 整型字段 ) II . 创建简单类 ( 整型字段 + 字符串字段 ) III . 类方法定义 IV . 封装 V . 继承 VI . 多态 与 抽象类 I . 创建简 ...
- c++虚继承和虚函数和抽象类、接口类,聚合类
虚继承 虚继承用于解决多继承条件下的菱形继承问题(浪费存储空间.存在二义性). 底层实现原理与编译器相关,一般通过虚基类指针和虚基类表实现,每个虚继承的子类都有一个虚基类指针(占用一个指针的存储空间, ...
- 虚继承,虚基类以及虚继承的构造函数
目录 一.什么是虚继承,虚基类 二.定义虚继承的基本格式 三.虚继承的构造函数 一.什么是虚继承,虚基类 虚继承:在继承定义中包含了virtual关键字的继承关系 虚基类:在虚继承体系中的通过virt ...
- 【C++】继承和派生、虚继承和虚基类、虚基类表和虚基类指针
继承和派生.虚继承和虚基类.虚基类表和虚基类指针 继承和派生 继承概述 继承基本概念 派生类中的成员 继承的内容 派生类定义 派生类访问控制 对象构造和析构 对象构造和析构的调用顺序 继承中的构造和析 ...
- sizeof()来求一个类的大小
基本概念 一个类的实例化对象所占空间的大小? 注意不要说类的大小,是类的对象的大小. 首先,类的大小是什么?确切的说,类只是一个类型定义,它是没有大小可言的. 用sizeof运算符对一个类型名操作,得 ...
最新文章
- 武汉约100所中小学将试点人工智能课,现面向社会遴选教材
- 教你配CISCO RIP(二)
- NYOJ 36 最长公共子序列 dp
- ubuntu16.04无法连接WiFi搜索不到网络网卡驱动
- 在Win10删除Ubuntu时直接删除分区后,如何删除启动项(EFI)
- MyBatis学习总结(21)——自定义MyBatis Generator插件
- 计算机继续教育笔记,《继续教育中的学习技术》读书笔记
- 在IT界取得成功应该知道的10件事(ZT)
- c语言中-(间接成员运算符)的含义
- java学习笔记(3.31)
- bbs的html代码,bbs论坛源代码
- js设计模式之策略模式
- SPDK/NVMe存储技术分析之用户态ibv_post_send()源码分析(一)
- python命名规则数字开头的成语_day01 Python基础
- HTML实现在线代码格式化、美化、加密、解密、压缩、一键转JavaScript功能工具-toolfk程序员工具网
- php 属猪,属猪人的流年运程
- Matomo API 官方接口详情
- 使用customRef自定义ref,解决setup中处理异步问题。
- ubuntu播放mp4的插件
- 使用JS实现博客搜索关键字高亮