C++程序运行时内存布局之----------无继承情况下的虚函数

本文探讨了在无继承情况下,带有虚函数的C++类及其实例的内存布局。通过源码、实验结果和内存布局图,揭示了虚函数表在data区的存储以及构造函数如何设置对象的vptr。同时指出,虚函数表项可能包含代理函数,用于间接调用虚函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

虚函数是C++实现多态的关键,没有虚函数,C++只能是OB,不能完成OO。对于VC++中虚函数的实现机制,有很多文章,我看过的是陈浩写的,链接如下:

http://blog.youkuaiyun.com/haoel/article/details/1948051。总觉得还是有些不太清楚的,所以自己做了进一步的实验,记录下来以供参考。

本文介绍的是没有继承情况下,带有虚函数的类在内存中布局,以及其实例(对象)内存布局。

 

1.源码

#include <iostream>
#include <stdio.h>

using namespace std;

class CVirtual
{
public:
	int x;
public:
	virtual void VF()
	{
		cout<<this->x<<endl;
		cout<<"hello"<<endl;
	}
public:
	CVirtual(int x)
	{
		this->x = x;
	}
};

typedef void (CVirtual::*Fun)();
union
{
	Fun f;
	unsigned int addr;
}ut;

int main(int argc, char** argv)
{
	//打印出类实例的大小
	cout<<"对象大小为                       :"<<sizeof(CVirtual)<<endl;

	CVirtual *p = new CVirtual(999);
	CVirtual *p1 = new CVirtual(888);

	//打印对象地址
	cout<<"新建对象的地址                   :"<<p<<endl;

	//打印第一个成员变量地址
	cout<<"对象中第一个成员变量的地址       :"<<&p->x<<endl;

	//打印虚函数的地址
	ut.f = &(CVirtual::VF);
	cout<<"类中第一个虚函数的地址           :"<<std::hex<<std::showbase<<ut.addr<<endl;

	//虚表指针
	unsigned int vptr = *((unsigned int*)p);
	cout<<"对象1中虚表指针(即虚表地址)为    :"<<std::hex<<std::showbase<<vptr<<endl;

	//虚表第一项值为
	unsigned slot0 = *((unsigned int*)vptr);
	cout<<"虚表中第一项的值(第一个虚函数地址):"<<std::hex<<std::showbase<<slot0<<endl;


	//虚表指针
	unsigned int vptr1 = *((unsigned int*)p1);
	cout<<"对象2中虚表指针(即虚表地址)为    :"<<std::hex<<std::showbase<<vptr1<<endl;

	//虚表第一项值为
	unsigned slot01 = *((unsigned int*)vptr1);
	cout<<"虚表中第一项的值(第一个虚函数地址):"<<std::hex<<std::showbase<<slot01<<endl;


	//虚函数的原型
	typedef void (__thiscall *MyFun)(void* pThis);

	//调用虚函数表中的第一个函数
	MyFun f = (MyFun)slot0;
	f(p);

	//调用虚函数
	MyFun f1 = (MyFun)ut.addr;
	f1(p);

	delete p;
	delete p1; 
	cin>>argc;
}

 

2.结果

 

3.内存布局图

4.结论

  • 虚函数表在编译期间已经确定,建立在data区,运行期只是把由构造函数把对象的vptr值设定为这个地址,同一个类的所有实例共享同一个虚函数表;
  • 虚函数表中的每一个项目不一定是虚函数的地址,很可能是一个代理函数,然后由代理函数再调用虚函数;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值