让我们举例如下:
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的受损名称是相同的.
虚拟表只是函数指针的数组,就像你的第二个代码片段一样.例如,编译器将对虚函数的调用转换为通过指针调用
Base * b = /* ... */;
b->function2();
Run Code Online (Sandbox Code Playgroud)
被翻译成
b->__vtable[1]();
Run Code Online (Sandbox Code Playgroud)
我使用该名称__vtable来引用虚拟表(但请注意,虚拟表通常不能直接访问).
表中条目的顺序由在类中声明函数的顺序确定.请记住,类定义始终在调用时可用.