指向不同地址的vTables和函数指针

Kun*_*shu 4 c++ memory-management vtable

我最近在bitsquid博客上阅读了一篇关于如何管理内存的文章,作者开始讨论vtable以及编译器如何将类添加到类中.这是该文章的链接.因为我几乎不知道关于这个问题的事情,所以我开始在网上寻找解释.我来到了这个链接.根据我读到的内容,我制作了以下代码:

char cache[24];

printf("Size of int = %d\n", sizeof(int));
printf("Size of A = %d\n", sizeof(A));

A* a = new(cache)A(0,0);
printf("%s\n",cache);
printf("vTable    : %d\n",*((int*)cache));
printf("cache addr: %d\n",&cache);

int* funcPointer = (int*)(*((int*)cache));
printf("A::sayHello: %d\n",&A::sayHello);
printf("funcPointer: %d\n",*funcPointer);
Run Code Online (Sandbox Code Playgroud)

A是一个具有两个整数成员和一个虚函数的类sayHello().

编辑:这是类定义:

class A {
public:
    int _x;
    int _y;
public:
    A(int x, int y) : _x(x), _y(y){ }
    virtual void sayHello() { printf("Hello You!"); }
};
Run Code Online (Sandbox Code Playgroud)

基本上我试图做的是看看vtable中的指针是否指向与我所从的地址相同的位置&A::sayHello,但问题是当我运行程序时,vtable中指针内的地址和sayHello()地址总是有区别的295.有谁知道为什么会发生这种情况?是否有某种标题被添加,我错过了?我在64位机器上运行visual studio express 2008.

从我调试的地址返回的*funcPointer是该函数的真实地址sayHello().但为什么&A::sayHello()返回一个不同的地址呢?

cra*_*jul 8

C++有一个有趣的特性:

如果您使用指向虚函数的指针并使用它,则将解析并调用虚函数.

我们举一个简单的例子

struct A
{
    virtual DoSomething(){ printf("A"); }
};

struct B: public A
{
    virtual DoSomething() { printf("B"); }
};

void main()
{
    A * a, b;
    void (A::*pointer_to_function)();

    pointer_to_function = &A::DoSomething;
    a = new A;
    b = new B;

    (a.*pointer_to_function)() //print "A"
    (b.*pointer_to_function)() //print "B"
}
Run Code Online (Sandbox Code Playgroud)

因此,您看到&A::DoSomething的地址是蹦床的地址,而不是真实的功能地址.

如果你去装配,你会看到该函数做了类似的事情(寄存器可能会改变,但ecx代表这个指针):

mov eax, [ecx] ; Read vtable pointer
lea edx, [eax + 4 * function_index ] ; function_index being the index of function in the vtable
call edx  
Run Code Online (Sandbox Code Playgroud)