90 C++对象模型探索。数据语义学 - 虚函数地址问题 vcall引用

我们先来看一段代码,进行debug问题分析。

class Teacher22 {
public:
	void virtual func1() {
		cout << "Teacher22 vir func1 called this = " << this << endl;
		
	}

	void virtual func2() {
		cout << "Teacher22 vir func2 called this = " << this << endl;
	}
};

void main() {
	//我们打印一下 func1 和func2的地址
	printf("Teacher22::func1 的地址是%p\n",&Teacher22::func1);

	printf("Teacher22::func2 的地址是%p\n", &Teacher22::func2);

	Teacher22 *ptea = new Teacher22();


	cout << "断点在这里" << endl;

}

问题:debug 和 打log发现虚函数的地址不一样。

打log    
Teacher22::func1 的地址是00B5121C
Teacher22::func2 的地址是00B515FF

在程序执行中debug
    [0] = 0x00b51802 {ConsoleApplication2.exe!Teacher22::func1(void)}
    [1] = 0x00b517fd {ConsoleApplication2.exe!Teacher22::func2(void)}

这两个不一样呀,那个是真的呢?

再次验证,在内存中 查找ptea的值,
Teacher22 *ptea = new Teacher22();
前四个值就是vptr的值,
    64 5e b6 00
    
    0x00b65e64
    再次查看内存 中 这个vptr的值
    
    02 18 b5 00 fd 17 b5 00
    也就是 00b51802   00b517fd
也就是说:

我们在程序debug中看到的是真实的值,

那么通过 Teacher22::func1打印的这个虚函数地址为什么有问题呢?

原因:


再次查看 反汇编代码,会发现,里面有一个vcall的调用,我们可以将vcall理解为一段代码, 
也就是说:在 &Teacher22::func1 中打印的实际上vcall的地址,然后通过vcall的调用真正的调用到虚函数中。
 

也就是说;通过

printf("Teacher22::func1 的地址是%p\n",&Teacher22::func1);

//实际上上面函数打印的是vcall函数地址,而不是真正的虚函数地址

为什么要有这个vcall?

1.在多重继承的时候,可以调整this指针的偏移。

2.跳转到真正的虚函数中去。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值