C++中虚函数继承类的内存占用大小计算
计算一个类对象的大小时的规律:
- 1、空类、单一继承的空类、多重继承的空类所占空间大小为:1(字节,下同);
- 2、一个类中,虚函数本身、成员函数(包括静态与非静态)和静态数据成员都是不占用类对象的存储空间的;
- 3、因此一个对象的大小≥所有非静态成员大小的总和;
- 4、当类中声明了虚函数(不管是1个还是多个),那么在实例化对象时,编译器会自动在对象里安插一个指针vPtr指向虚函数表VTable;
- 5、虚承继的情况:由于涉及到虚函数表和虚基表,会同时增加一个(多重虚继承下对应多个)vfPtr指针指向虚函数表vfTable和一个vbPtr指针指向虚基表vbTable,这两者所占的空间大小为:8(或8乘以多继承时父类的个数);
- 6、在考虑以上内容所占空间的大小时,还要注意编译器下的“补齐”padding的影响,即编译器会插入多余的字节补齐;
- 7、类对象的大小=各非静态数据成员(包括父类的非静态数据成员但都不包括所有的成员函数)的总和+ vfptr指针(多继承下可能不止一个)+vbptr指针(多继承下可能不止一个)+编译器额外增加的字节。
例子一
class A
{
};
class B
{
char ch;
virtual void func0() { }
};
class C
{
char ch1;
char ch2;
virtual void func() { }
virtual void func1() { }
};
class D: public A, public C
{
int d;
virtual void func() { }
virtual void func1() { }
};
class E: public B, public C
{
int e;
virtual void func0() { }
virtual void func1() { }
};
int main(void)
{
cout<<"A="<<sizeof(A)<<endl; //result=1
cout<<"B="<<sizeof(B)<<endl; //result=8
cout<<"C="<<sizeof(C)<<endl; //result=8
cout<<"D="<<sizeof(D)<<endl; //result=12
cout<<"E="<<sizeof(E)<<endl; //result=20
return 0;
}
求sizeof(D)的时候,需要明白,首先VPTR指向的虚函数表中保存的是类D中的两个虚函数的地址,然后存放基类C中的两个数据成员ch1、ch2,注意内存对齐,然后存放数据成员d,这样4+4+4=12。
求sizeof(E)的时候,首先是类B的虚函数地址,然后类B中的数据成员,再然后是类C的虚函数地址,然后类C中的数据成员,最后是类E中的数据成员e,同样注意内存对齐,这样4+4+4+4+4=20。
例二含有虚继承
class A
{
public:
virtual void aa() { }
virtual void aa2() { }
private:
char ch[3];
};
class B: virtual public A
{
public:
virtual void bb() { }
virtual void bb2() { }
};
int main(void)
{
cout<<"A's size is "<<sizeof(A)<<endl;
cout<<"B's size is "<<sizeof(B)<<endl;
return 0;
}
A's size is 8
B's size is 16
说明:对于虚继承,类B因为有自己的虚函数,所以它本身有一个虚指针,指向自己的虚表。另外,类B虚继承类A时,首先要通过加入一个虚指针来指向父类A,然后还要包含父类A的所有内容。因此是4+4+8=16。
C++中虚函数继承类的内存占用大小计算的更多相关文章
- 虚函数列表: 取出方法 // 虚函数工作原理和(虚)继承类的内存占用大小计算 32位机器上 sizeof(void *) // 4byte
#include <iostream> using namespace std; class A { public: A(){} virtual void geta(){ cout < ...
- 从零开始学C++之虚继承和虚函数对C++对象内存模型造成的影响
首先重新回顾一下关于类/对象大小的计算原则: 类大小计算遵循结构体对齐原则 第一个数据成员放在offset为0的位置 其它成员对齐至min(sizeof(member),#pragma pack(n) ...
- C++ 在继承中虚函数、纯虚函数、普通函数,三者的区别
1.虚函数(impure virtual) C++的虚函数主要作用是“运行时多态”,父类中提供虚函数的实现,为子类提供默认的函数实现. 子类可以重写父类的虚函数实现子类的特殊化. 如下就是一个父类中的 ...
- <转>C++继承中虚函数的使用
转自:http://blog.csdn.net/itolfn/article/details/7412364 一:继承中的指针问题. 1. 指向基类的指针可以指向派生类对象,当基类指针指向派生类对 ...
- C++中虚函数的作用浅析
虚函数联系到多态,多态联系到继承.所以本文中都是在继承层次上做文章.没了继承,什么都没得谈. 下面是对C++的虚函数这玩意儿的理解. 一, 什么是虚函数(如果不知道虚函数为何物,但有急切的想知道,那你 ...
- C++中虚函数的作用是什么?它应该怎么用呢?(转)
虚函数联系到多态,多态联系到继承.所以本文中都是在继承层次上做文章.没了继承,什么都没得谈. 下面是对C++的虚函数这玩意儿的理解. 一, 什么是虚函数(如果不知道虚函数为何物,但有急切的想知道,那你 ...
- C++中虚函数的作用
一, 什么是虚函数(如果不知道虚函数为何物,但有急切的想知道,那你就应该从这里开始) 简单地说,那些被virtual关键字修饰的成员函数,就是虚函数.虚函数的作用,用专业术语来解释就是实现多态性(Po ...
- C++中虚函数的作用是什么?它应该怎么用呢?
虚函数联系到多态,多态联系到继承.所以本文中都是在继承层次上做文章.没了继承,什么都没得谈. 下面是对C++的虚函数这玩意儿的理解. 一, 什么是虚函数(如果不知道虚函数为何物,但有急切的想知道,那你 ...
- c++中虚函数
虽然很难找到一本不讨论多态性的C++书籍或杂志,但是,大多数这类讨论使多态性和C++虚函数的使用看起来很难.我打算在这篇文章中通过从几个方面和结合一些例子使读者理解在C++中的虚函数实现技术.说明一点 ...
随机推荐
- ASP.NET Core中使用Dapper
⒈添加 NuGet 包 Install-Package Dapper ⒉封装数据库类型 using System; using System.Collections.Generic; using Sy ...
- # [洛谷1337] 吊打XXX/平衡点 (模拟退火)
[洛谷1337] 吊打XXX/平衡点 (模拟退火) 题意 n个重物(x,y,w),求平衡时x的位置(x,y) 分析 模拟退火基础题,基于随机数的优化算法,时间复杂度玄学,参数玄学,能不能AC看脸,当然 ...
- Snoopy.class.php使用手册
Snoopy - the PHP net client v1.2.4 Snoopy是一个php类,用来模拟浏览器的功能,可以获取网页内容,发送表单.Snoopy的特点:1.抓取网页的内容 fetch2 ...
- wc、iconv命令
一.wc:统计文件打印换行符,单词和字节数 语法: wc [OPTION] ... [FILE] ... wc [OPTION] ... --files0-from = F 描 ...
- Stardew Valley(星露谷物语)Mod开发之路 1环境配置
首先来说明一下,我写这个章节本身也是对学习过程的记录,主要参考了http://canimod.com/guides/creating-a-smapi-mod中的内容.也推荐大家看看. *这些是我的开发 ...
- java 字节流与字符流的区别(转)
字节流与和字符流的使用非常相似,两者除了操作代码上的不同之外,是否还有其他的不同呢? 实际上字节流在操作时本身不会用到缓冲区(内存),是文件本身直接操作的,而字符流在操作时使用了缓冲区,通过缓冲区再操 ...
- 可以用for循环直接删除ArrayList的特定元素吗?可能会出现什么问题?怎样解决?
for循环直接删除ArrayList中的特定元素是错的,不同的for循环会发生不同的错误,泛型for会抛出 ConcurrentModificationException,普通的for想要删除集合中重 ...
- mac 下安装mysql
1.安装mysql 使用 brew 进行安装: brew install mysql 2.安装完成: 3.如果开机启动服务 执行:brew services start mysql 否则:mysql. ...
- ZooKeeper--动物管理员
复杂的软件集群系统从来绕不开高可用.负载均衡等问题,大数据系统更是如此. 高可用:计算机系统的可用性定义为系统保持正常运行时间的百分比,具体手段有自动检测,自动切换,自动恢复等. 负载均衡:主要解决单 ...
- sql分页查询(2005以后的数据库)和access分页查询
sql分页查询: select * from ( select ROW_NUMBER() over(order by 排序条件) as rowNumber,* from [表名] where 条件 ) ...