C++中vtable的函数解析
Function resolution from vtable in C++
在阅读了更多关于名称篡改的内容后,我对vtable感到困惑。例如:
class Base
{
public:
virtual void print()
{
}
};
class A : public Base
{
public:
void hello()
{
....
}
void print()
{
}
};
A obj;
obj.hello();
Base* test = new A();
test->print();
根据我的理解,在名称篡改后,obj.hello()
调用现在将转换为类似_ZASDhellov(&obj)
的
- 如何从vtable调用这些虚拟函数
- 我胡乱猜测
test->__vtable[_ZASDprintv](&test(dynamic cast to derived???))
是对的 - 如何从vtable解析函数名
首先,vtables在任何方面都不是C++语言的一部分,而是特定编译器使用的实现细节。下面我描述一种常用的方式。
其次,您的函数hello
不是虚拟的。为了使它成为虚拟的,您只需将virtual
预挂接到声明中。
假设它现在是虚拟的:你的猜测非常接近。事实上,vtable
(指向它的指针与虚拟类的每个实例一起存储(是一个函数指针数组。在其中查找特定函数的方式是通过其序数。A
中第一个声明的虚拟函数是其vtable
中的第一个条目,第二个是第二个条目,依此类推。如果A
有基类,则A
在表中的第一(非重写(虚拟函数的索引将是n+1
,其中n
是其基类的最后一个虚拟函数的索引。如果A
有多个基类,则它们的条目按照声明为A
基类的顺序位于A
的条目之前。
如果A
使用虚拟继承,情况会比这复杂一些,除非你特别感兴趣,否则我不会详细说明。
更新:我将根据请求为虚拟继承案例添加一个非常简短的描述。如果A
将Base
作为虚拟基类,则A
的vtable
将在A
对象中Base
的数据起始位置的最开始(在函数地址之前(存储字节偏移量。这是必要的,因为与正常继承不同,基类的数据不在派生类的数据之前,而是在派生类之后。因此,实际上,对Base
中定义的虚拟函数的任何函数调用都必须使其this
指针偏移该量。此外,Base
必须有自己的vtable
指针,就在它希望找到它的数据的开头。因此,完整的A
对象将包含两个vtable
指针,而不是一个。由该第二指针指向的实际vtable
将与第一vtable
指针相同,除了前进以跳过上述偏移条目(使得使用vtable
的任何Base
代码将在预期的开始处找到第一虚拟函数(。除了这些差异之外,vtable
本身与以前相同。
- 为什么 fdump-class-hierarchy 为虚函数提供了两个指针 int vtable
- 虚拟函数在哪里使用 vpointer to vtable 来解析方法调用,非虚拟方法存储在哪里以及如何解析它们?
- 为什么虚拟类的析构函数不会自动添加到 vtable 中?
- 防止派生析构函数中的 vtable 数据争用
- 正在读取虚拟函数表 (vtable) 指针?
- 为每个抽象函数定义主体后,对VTable的不确定引用
- 是否会动态调度在具有 vtable 的类上调用非虚函数
- 构造函数中对"vtable"的未定义引用
- 基类的虚拟和最终函数的成本(vtable/虚拟成本)
- 我明白为什么,但是虚拟函数/VTable 究竟如何允许通过指针访问正确的函数?
- 构造函数中对 vtable 的未定义引用
- C++ 虚拟析构函数和 vtable
- 关于vtable符号可能未定义,因为类缺少其键函数
- "vtable"链接器错误(涉及带有"=default"的虚拟析构函数) - Clang 3.1 中的潜在错误?
- 实现虚拟函数时对 vtable 的未定义引用
- c++:vtable是否包含指向非虚拟函数的指针
- 是当虚拟函数立即标记为final时生成的vtable
- 析构函数"Missing vtable",但定义了析构函数
- 构造函数/解构函数情况下的'undefined reference to vtable for'
- C++虚拟函数.vtable的问题