VTABLE中的地址与直接地址之间的差异

时间:2015-11-30 17:43:13

标签: c++

#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)()

为什么在表格中,我们保留地址的修改值?

1 个答案:

答案 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*相同的内容到函数的实际代码。但至少在正确的间接水平下,你会将其与之比较。

相关问题