因为C ++中的所有虚函数都存储在V-table中。在虚函数的情况下发生重叠。 我想问一下,我们可以通过哪种方式直接从表中调用虚函数,并且能够确定V-table包含哪些函数。
答案 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包含该类的所有虚方法。您可以反汇编应用程序以查看它们。