从V-table调用虚函数

时间:2013-06-14 10:29:15

标签: c++ virtual-functions vtable

因为C ++中的所有虚函数都存储在V-table中。在虚函数的情况下发生重叠。 我想问一下,我们可以通过哪种方式直接从表中调用虚函数,并且能够确定V-table包含哪些函数。

4 个答案:

答案 0 :(得分:17)

嗯,实际上你可以。我不关心可移植性,但在VS中你可以做到。 假设我们使用VS构建32位代码,对象地址的前4个字节是vtable地址。通过查看头文件,我们知道了vtable中方法的顺序。

示例:

class Base
{
public:

    virtual void printMessage()
    {
        std::cout << "Base::printMessage()" << std::endl;
    }
};

class Derived : public Base
{
public:

    void printMessage()
    {
        std::cout << "Derived::printMessage()" << std::endl;
    }
};

int main(int argc, char* argv[])
{
    Derived d;

    unsigned int vtblAddress = *(unsigned int*)&d;

    typedef void(*pFun)(void*);

    pFun printFun = (pFun)(*(unsigned int*)(vtblAddress));

    printFun(&d);

    return 0;
}

P.S。 我不会问为什么你这样做,但在这里你有一个选择: - )

答案 1 :(得分:2)

标准无法保证使用v-table实现虚拟功能。因此,只有您确定,该编译器使用v-table - 您才能找到所需的偏移量。

答案 2 :(得分:2)

Portly,没有。该语言未指定虚拟调度的实现方式,仅指定其行为方式。它不一定使用v-table实现,除了调用它之外无法访问虚函数。

如果您只需要支持一个特定的ABI,那么您可以使用实现细节以及一些狡猾的指针强制转换,以与虚拟分派机制相同的方式将对象映射到函数指针。但是你将超越定义的语言进入不受支持的非便携领域,所以我肯定会建议你重新思考你想要做的事情。

答案 3 :(得分:0)

我一般会说不,因为vtable的确切实现是特定于平台/编译器的。如果您知道平台/编译器如何实现vtable和addresation,则可以通过确定特定类的vtable的地址然后添加虚拟方法的偏移量来计算它。

vtable包含该类的所有虚方法。您可以反汇编应用程序以查看它们。