gpt4 book ai didi

c++ - 可以为虚函数实现绕过 vtable 吗?

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:20:26 26 4
gpt4 key购买 nike

而不是在对象中查找 vtable 指针的地方使用虚函数,然后将您带到 vtable,包含指向函数的指针 - 是否不可能只在对象中包含一个数据成员哪个直接指向函数?

最佳答案

如果我理解你的问题,你正在寻找一种使用函数指针实现多态性的方法。

嗯,这是可能的,但非常麻烦,容易出错,而且很难胜过编译器为虚函数调用生成的 de。

怎么做?

想法是使用函数指针。为了实现多态,它必须在基类中。

class B {                   // Base class
protected:
void (B::*fptest)(); // Function pointer to member function
public:
void mtest() // Class specific mebmer function
{ cout << "Base test\n"; }
void itest() // Polymorphic function
{ (this->*fptest)(); } // implemented by calling the poitner to member function
B() : fptest(&B::mtest) { } // Ctor must initialize the function pointer
virtual ~B() {}
};

class D : public B { // Derived class
public:
void mtest() // Class specific mebmer function
{ cout << "Derived test\n"; }
D() // Ctor
{ fptest = reinterpret_cast<void(B::*)()>(&D::mtest); } // not sure it's this safe in case of multiple inheritance !!
};

测试这个结构的代码:

B b; 
D d;
B *pb = &b, *pd = &d;
pb->itest();
pd->itest();

安全吗?

对此有严格的限制。例如:

  • 您必须确保每个派生类都正确初始化函数指针。
  • 在多重继承的情况下,转换为基类成员的函数指针可能无法按预期工作。
  • 不可能有指针重载。因此,您需要为每个可能的签名使用不同的指针。那可能很奇怪。

它比 vtable 查找更高效吗?

否:查看对 itest() 的每个多态调用执行的汇编程序:

; 41   :    pd->itest();  // cod for the call for a derived object
mov ecx, DWORD PTR _pd$[ebp] ; load the oject address
call ?itest@B@@QAEXXZ ; call B::itest
; 16 : void itest() { (this->*fptest)(); }
push ebp
mov ebp, esp
sub esp, 68 ; 00000044H
push ebx
push esi
push edi
mov DWORD PTR _this$[ebp], ecx ; use address of object as parameter
mov eax, DWORD PTR _this$[ebp] ; load the function pointer
mov ecx, DWORD PTR _this$[ebp] ; " "
mov edx, DWORD PTR [eax+4] ; call the function pointer
call edx
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 0

当然,优化器可以内联代码,删除一些 push 和 pop,但一般原则是将生成间接代码。

vtable 查找性能不够吗?

好吧,vtable 查找基本上是从编译器计算的固定偏移量加载函数指针。调用虚拟 test() 函数的汇编代码如下所示:

 39   :     pd->test(); 
mov eax, DWORD PTR _pd$[ebp]
mov edx, DWORD PTR [eax]
mov ecx, DWORD PTR _pd$[ebp]
mov eax, DWORD PTR [edx]
call eax

结论

vtable 查找至少与通过函数指针调用一样高效。编译器负责所有的初始化和最复杂的继承情况。最好使用强大的虚函数,而不是试图手动超越你的编译器。

关于c++ - 可以为虚函数实现绕过 vtable 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27113595/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com