c ++虚拟表查找 - 如何搜索和替换

har*_*ish 6 c++ virtual

让我们举例如下:

class Base{
    virtual string function1(){ return "Base - function1"; };
    virtual string function2(){ return "Base - function2"; };
};

class Derived : public Base {
    virtual string function2(){ return "Derived - function2"; };
    virtual string function1(){ return "Derived - function1"; };
    string function3() { return "Derived - function3"; };
};
Run Code Online (Sandbox Code Playgroud)

所以vtable结构就像

Base-vTable
-----------------------
name_of_function address_of_function
function1   &function1
function2   &function2
-----------------------
-----------------------
Derived-vTable
-----------------------
name_of_function address_of_function
function1   &function1
function2   &function2
Run Code Online (Sandbox Code Playgroud)

还是喜欢

    Base-vTable
-----------------------
    Offset function
    +0  function1
    +4  function2
-----------------------
-----------------------
    Derived-vTable
-----------------------
    Offset function
    +0  function1
    +4  function2
Run Code Online (Sandbox Code Playgroud)

如果它像后者?然后是什么偏移?在哪里使用?

而且函数名称是:它是错误的函数名吗?如果它被破坏,那么基础和派生的受损名称将不匹配,并且vtable查找不起作用.编译器会破坏所有虚函数名称,因此它必须是一个受损的名称,这是否意味着如果它是虚函数,base和derived的受损名称是相同的.

ava*_*kar 8

虚拟表只是函数指针的数组,就像你的第二个代码片段一样.例如,编译器将对虚函数的调用转换为通过指针调用

Base * b = /* ... */;
b->function2();
Run Code Online (Sandbox Code Playgroud)

被翻译成

b->__vtable[1]();
Run Code Online (Sandbox Code Playgroud)

我使用该名称__vtable来引用虚拟表(但请注意,虚拟表通常不能直接访问).

表中条目的顺序由在类中声明函数的顺序确定.请记住,类定义始终在调用时可用.

  • @harish:它在编译期间存储为瞬态信息,但未在生成的最终二进制文件中编码.由于算法是确定性的(通常它只是按声明的顺序获取虚函数),编译器不需要存储它,它可以在需要时从源文件中重新计算它,并且偏移量`__vtable [1]`是在编译时在二进制文件中进行硬编码. (3认同)

nim*_*odm 2

第二种情况——假设指针占用 4 个字节(32 位机器)。

函数名称永远不会存储在可执行文件中(调试除外)。虚表只是函数指针的向量,由运行代码直接访问。