C++ 对象内存布局和多态实现原理

本文详细探讨了C++中类的内存布局,从空类到普通类,再到继承、多重继承、虚拟继承的情况。讨论了空类、包含成员变量的类、静态成员以及虚函数如何影响内存布局。特别地,文章深入解析了虚函数表(vftable)和虚函数指针(vptr)在实现多态中的作用,解释了如何通过vfptr和vftable实现多态调用。同时,文章还介绍了虚拟继承下的内存布局以及钻石继承问题,展示了不同编译器可能存在的实现差异。
摘要由CSDN通过智能技术生成

进入主题前,先把工具设置好。本文使用编译测试环境:Visual Studio 2013

VS2013查看类内存布局设置方式如下截图:



先选择左侧的C/C++->命令行,然后在其他选项这里写上/d1 reportAllClassLayout,它可以看到所有相关类的内存布局,如果写上/d1 reportSingleClassLayoutXXX(XXX为类名),则只会打出指定类XXX的内存布局。


进入主题:从最基础的class到继承、多重继承、虚拟继承,我们依次展开来看。

1.空类

定义一个空类,如下:

class Base {

};
编译一下,可以看到输出框里面的布局:


发现空类Base的size是1,原因:C++标准规定,编译器为空类插入1字节的char,以使该类对象在内存得以配置一个地址。

2.普通类(只有nonstatic的成员变量

定义如下:

class Base {
private:
	int a;
	int b;
};
内存布局:


这里暂不考虑字节对齐的影响,所以成员变量都设为int型。从这里可以看到普通类的布局方式,nonstatic成员变量依据声明的顺序进行排列(类内偏移为0开始)。

当涉及字符对齐时的内存布局图。

定义如下:

class Base {
private:
	int a;
	char b;
};
内存布局:


从上图红色框图中,看到char b会被4byte对齐,Base object size是8,而不是5。

当在继承体系中,父类和子类都涉及字节对齐时,我们来看下内存布局状况。

定义如下:

class Base {
private:
	int a;
	char b;
};

class Derived : public Base{
private:
	int c;
	char d;
};
内存布局:


从上图红色框图中,看到Base suboject char b和Derived char d 都被4byte对齐,Derived object size是16。int c的内存并不是从位置5开始,而是从8开始。在继承中char b依然会如Base对象中被4byte对齐处理。这是因为:继承关系中派生类会保持基类subobject的内存布局完整性。

3.普通类(加上static成员和普通function

定义如下:

class Base {
public:
	void f();
	static void g();
private:
	int a;
	static int c;
	int b;
};
内存布局:


可以看出:static成员变量、static成员函数,普通成员函数,都不会占用对象的空间。static成员属于class,所有object共用一份。

4.普通类(加上虚函数

定义如下:

class Base {
public:
	void f();
	virtual void g();
private:
	int a;
	int b;
};
内存布局:

这个结构图分成上下两部分,上面是内存分布,下面是虚函数表vftable(也称作vtbl)。我们看到class Base size现在是12,除去两个int变量占用8个Byte,虚函数表指针vfptr(也称作vptr&#x

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值