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.跳转到真正的虚函数中去。

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-01-31 08:34:01       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-01-31 08:34:01       106 阅读
  3. 在Django里面运行非项目文件

    2024-01-31 08:34:01       87 阅读
  4. Python语言-面向对象

    2024-01-31 08:34:01       96 阅读

热门阅读

  1. BERT问答模型回答问题

    2024-01-31 08:34:01       47 阅读
  2. 大数据存储与处理技术之Spark

    2024-01-31 08:34:01       47 阅读
  3. C++ 实现单例模式

    2024-01-31 08:34:01       50 阅读
  4. Vue 甘特图 gantt 安装使用

    2024-01-31 08:34:01       52 阅读
  5. 分布式集群如何保证线程安全

    2024-01-31 08:34:01       49 阅读
  6. 贪吃蛇游戏中显示贪吃蛇的路线和蛇的宽度

    2024-01-31 08:34:01       51 阅读