【发布时间】:2018-09-06 18:03:16
【问题描述】:
我从虚拟表中的地址调用虚拟函数作为一个练习,以测试我对这个概念的理解。然而,当我以为我对虚拟方法表的理解有了突破时,我又遇到了一个我只是不明白的问题。
在下面的代码中,我创建了一个名为Car 的类,其中包含一个成员变量x 和两个虚函数,first 和second。现在,我通过破解虚拟表来调用这两个虚拟方法。第一个函数返回正确答案,但第二个函数返回一些随机值或垃圾,而不是初始化的值。
#include <cstdio>
class Car
{
private:
int x;
virtual int first()
{
printf("IT WORKS!!\n");
int num = 5;
return num;
}
virtual int second()
{
printf("IT WORKS 2!!\n");
//int num = 5;
return x;
}
public:
Car(){
x = 2;
}
};
int main()
{
Car car;
void* carPtr = &car;
long **mVtable =(long **)(carPtr);
printf("VTable: %p\n", *mVtable);
printf("First Entry of VTable: %p\n", (void*) mVtable[0][0]);
printf("Second Entry of VTable: %p\n", (void*) mVtable[0][1]);
if(sizeof(void*) == 8){
printf("64 bit\n");
}
int (*firstfunc)() = (int (*)()) mVtable[0][0];
int x = firstfunc();
int (*secondfunc)() = (int (*)()) mVtable[0][1];
int x2 = secondfunc();
printf("first: %d\nsecond: %d", x, x2);
return 0;
}
如果有人能指出我做错了什么,那将不胜感激。此外,由于这在编译器中的工作方式不同,我正在使用 c++14 在http://cpp.sh/ 上对其进行测试。
该代码输出输出,其中“垃圾”第二个输出可能会发生变化:
VTable: 0x400890
First Entry of VTable: 0x400740
Second Entry of VTable: 0x400720
64 bit
IT WORKS!!
IT WORKS 2!!
first: 5
second: -888586240
【问题讨论】:
-
对于
Car的哪个实例,您通过指针secondfunc调用函数second? -
你能转换成成员函数指针而不是函数指针吗?
-
在调用对象的方法之前,您没有提供对象的地址(通过 x86/AMD ABI,前六个参数放在寄存器中)。
-
好的。我明白为什么它现在不起作用了。但是,现在我需要弄清楚如何才能真正做到这一点。我不知道这是否可能,但维基建议它是。 en.wikipedia.org/wiki/Virtual_method_table#Invocation
标签: c++ c++14 member-function-pointers virtual-functions virtual-table