#include <iostream>
#include <vector>
using namespace std;
class Foo
{
public:
virtual void f1()
{
cout << "Foo::f1()" << endl;
}
virtual void f2()
{
cout << "Foo::f2()" << endl;
}
virtual void f3()
{
cout << "Foo::f3()" << endl;
}
};
int main()
{
typedef void(*MethodFoo_f)();
Foo* ptr = new Foo();
cout << "Object address: " << ptr << endl;
cout << "__vfptr: " << (int*)*((int*)ptr) << endl;
for(int i = 0; i < 3; ++i)
{
int* e = (int*)*((int*)ptr) + i;
cout << "Address from __vfptr " << e;
auto t = &Foo::f1;
switch(i)
{
case 0: t = &Foo::f1; cout << ", address from main " << (void*&)t << " "; break;
case 1: t = &Foo::f2; cout << ", address from main " << (void*&)t << " "; break;
case 2: t = &Foo::f3; cout << ", address from main " << (void*&)t << " "; break;
}
cout << "execute: ";
auto func = (MethodFoo_f*)(e);
(*func)();
}
}
大家好,你能解释一下:为什么我们可以看到相同方法的地址不同。
Visual Studio的示例输出
对象地址:007ADE28 __vfptr:00E63B34
来自__vfptr 00E63B34的地址,来自主00E51F23的地址执行: FOO :: F1()
来自__vfptr 00E63B38的地址,来自主00E51F1E的地址执行: FOO :: F2()
来自__vfptr 00E63B3C的地址,来自主00E51F19的地址执行: FOO :: F3()
如果VTABLE调用transforme到
objPointer->(__vfptr + methodIndex)()
为什么在表格中,我们保留地址的修改值?
答案 0 :(得分:2)
我终于意识到了你想要的东西,你错过了一个层次的间接。
ptr
指向对象
(假设32位和许多其他事情你不应该真正假设):
*((int*)ptr)
是vtable的地址
(int*)*((int*)ptr)
*((int**)ptr)
是同一地址的演员
(int*)*((int*)ptr)+i
& (*((int**)ptr))[i]
是vtable中的一个位置,您想要该位置的内容:
*((int*)*((int*)ptr)+i)
或(*((int**)ptr))[i]
您可以在func
中获得额外的间接级别
MethodFoo_f
是指向函数的指针的类型,func
是指向MethodFoo_f
的指针。
因此,对于每个函数,您期望相同的数字是指向函数的指针和指向函数的简单指针。
我仍然不会猜测从auto t = &Foo::f1;
获得的函数指针可靠地具有与void*
相同的内容到函数的实际代码。但至少在正确的间接水平下,你会将其与之比较。