C++虚函数实现原理

前言

C++中的虚函数的作用主要是实现了多态的机制。基类定义虚函数,子类可以重写该函数。

实现机制

每个类对象添加一个成员,该成员中保存了一个指向函数地址数组的指针,称为虚表指针(vptr),该数组称为虚函数表(virtual function table, vtbl),即,每个类使用一个虚函数表,每个类对象用一个虚表指针。

实例分析

测试代码及输入结果

#include <iostream>
using namespace std;

class Base
{
public:
	virtual void a() { cout << "Base fun a" << endl; }
	virtual void b() { cout << "Base fun b" << endl; }
	virtual void c() { cout << "Base fun c" << endl; }
private:
	int x;
};

class Child : public Base
{
	virtual void b() { cout << "Child fun b" << endl; }
};

int main()
{
	typedef void(*Fun)(void);

	Child c;
	int x = sizeof(c);/* x=8 (x86) */
	int* pBase = (int*)(&c);
	cout << "对象地址:" << pBase << endl;
	int* pFun = (int*)(*pBase);
	cout << "虚函数表地址:" << pFun << endl;

	Fun pFun1 = (Fun)*(pFun + 0);
	pFun1();
	Fun pFun2 = (Fun)*(pFun + 1);
	pFun2();
	Fun pFun3 = (Fun)*(pFun + 2);
	pFun3();

    return 0;
}

说明:定义了基类Base,包含三个虚函数a、b、c和一个int成员变量x,子类Child重新实现了函数b。
在vs2015 x86下编译运行输出如下:
对象地址:0036F7BC
虚函数表地址:011A9C80
Base fun a
Child fun b
Base fun c

结果分析

  1. sizeof(C)结果为8,是因为在32位处理器上,虚标指针占用4字节,成员变量x占用4字节。
  2. 查看对象地址0x0036F7BC,其内存前四个字节正好是虚函数表的地址0x011A9C80(由于inter处理器是小端模式,所以字节序看起来刚好相反)。
    对象内存分布
  3. 查看虚函数表地址处的内存0x011A9C80,可以看到对象c包含的虚函数的具体地址,其中第一个和第三个为基类Base的a、c函数地址,第二个为子类Child的b函数地址。
    虚函数表内存分布
  4. 对象c在内存中函数地址分布示意图如下图所示:

虚函数表内存分布示意图
虚函数表指针保存在对象起始地址的前4字节(x64为8字节),其后紧跟的为成员变量。注意,前4字节是只存储了对象的虚函数表的地址,虚函数表存储在该地址指向的地址区。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值