7

因为 C++ 中的所有虚函数都存储在 V-table 中。覆盖发生在虚函数的情况下。 我想问有什么方法可以直接从表中调用虚函数,并且能够确定 V-table 包含哪些函数。

4

4 回答 4

19

嗯,其实你可以。我不关心可移植性,但在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;
}

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

于 2013-06-14T10:49:02.430 回答
2

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

于 2013-06-14T10:33:51.000 回答
2

便携,没有。该语言没有指定虚拟调度是如何实现的,只指定它的行为方式。它不一定使用v-table来实现,除了调用它之外没有办法访问虚函数。

如果您只需要支持一个特定的 ABI,那么您可以使用实现细节以及一些狡猾的指针转换,以与虚拟调度机制相同的方式将对象映射到函数指针。但是你会跨出定义的语言进入不受支持的、不可移植的领域,所以我绝对建议你重新考虑你想做的任何事情。

于 2013-06-14T10:33:58.717 回答
0

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

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

于 2013-06-14T10:35:50.180 回答