没有多态的虚拟C++方法

yzxexxkh  于 2022-11-19  发布在  其他
关注(0)|答案(3)|浏览(144)

假设您有这个简单的类层次结构:

struct base {

   virtual void f () const = 0;

};

struct derived : public base {

   virtual void f () const final
   {
      ...
   }   

};

f()只有一个实现,并且因为它被声明为final,我们是否可以认为没有多态性?
如果是这样,编译器是否会因为“不用就不用"而避免使用虚拟表来优化代码?

  • 谢谢-谢谢
s71maibg

s71maibg1#

存在多态是因为存在虚函数,并且可以从基类定义其他派生类。
从C++ 17标准(13.3虚拟函式)
1 [注意:虚函数支持动态绑定和面向对象的编程。- end note ]声明或继承虚函数的类称为多态类。

nx7onnlm

nx7onnlm2#

编译器是否会通过避免使用虚拟表来优化代码
如果编译器有一个pDerived->f(),那么是的,这是它通常会做的,因为这是final最初设计的目的。
如果它有一个pBase->f(),则只有当编译器能够证明pBase指向derived而不是从base派生的任何其它类时,这种优化才是可能的。f是否被声明为final与该分析无关。编译器通常一次只能看到一个翻译单元,因此需要进行某种数据流分析来消除这种可能性。链接时优化在这里并没有真正的帮助,因为额外的模块可以在运行时加载,而链接时优化器看不到它们。

yqlxgs2m

yqlxgs2m3#

我在编译器资源管理器中做了一个例子:https://godbolt.org/z/exsx8dzra
代码:

struct base {

virtual int f () const = 0;

};

struct derived : public base {

virtual int f () const final { return 2; }

};

int returnf(const base& b)
{
    return b.f();
}

程序集(x86-64 gcc12.2,-标准=c++20 -O3):

main:
 xor    eax,eax
 ret    
 cs nop WORD PTR [rax+rax*1+0x0]
 nop    DWORD PTR [rax]
returnf(base const&):
 mov    rax,QWORD PTR [rdi]
 mov    rax,QWORD PTR [rax]
 cmp    rax,0x401140
 jne    401138 <returnf(base const&)+0x18>
 mov    eax,0x2
 ret    
 nop    DWORD PTR [rax+0x0]
 jmp    rax
 nop    WORD PTR [rax+rax*1+0x0]
derived::f() const:
 mov    eax,0x2
 ret    
 cs nop WORD PTR [rax+rax*1+0x0]

在这里,您可以在程序集中看到虚函数调用没有完全优化掉,也就是说,仍然要检查对象是否是派生的类型:

cmp    rax,0x401140
 jne    401138 <returnf(base const&)+0x18>

如果是,则返回方法中指定的值,否则跳转到rax

相关问题