标记为“virtual final”的基本 class 方法是否会引入额外的开销?

Does a base class method marked as `virtual final` introduce additional overhead?

假设我想要一个 class Base 有两种方法:foo(int)bar(int)。我希望它们的定义方式如下:

第一个objective可以通过将foo标记为virtual int foo(int) = 0来完成,使其抽象化。第二个要求可以通过将 bar 标记为 virtual int bar(int) final 使其成为最终要求来满足。这是结果代码:

class Base
{
public:
    virtual int foo(int n) = 0;
    virtual int bar(int n) final
    {
        return n + 42;
    }
};

还有一个例子 class 来自 Base:

class Derived : public Base
{
public:
    virtual int foo(int n) override
    {
        return n * n;
    }
    int bar(int n) // compilation error here
    {
        return n + 43;
    }
};

尝试覆盖 Base::bar 已如我们所愿触发编译错误。

现在,我的问题是:将方法标记为 virtual final 是否会引入开销,因为函数是 virtual(动态调度),即使该函数无论如何都不能被覆盖?

编辑

不要介意缺少虚拟析构函数~Base()它不是为了让代码更短。

在你的情况下没有开销,因为你的 class 没有继承任何 class 定义你的最终函数,因此无论虚拟声明如何,编译器都会直接调用它的地址。

这是来自实际代码:

b->FoA(); //virtual inherited
002829A7  mov         eax,dword ptr [b]  
002829AA  mov         edx,dword ptr [eax]  
002829AC  mov         esi,esp  
002829AE  mov         ecx,dword ptr [b]  
002829B1  mov         eax,dword ptr [edx]  
002829B3  call        eax  
002829B5  cmp         esi,esp  
002829B7  call        __RTC_CheckEsp (02812E9h)  
    b->FoB(); // final
002829BC  mov         ecx,dword ptr [b]  
002829BF  call        A::FoB (0281366h)  

编译器可能会将此调用去虚拟化:

struct Base {
    virtual int bar(int n) final {
        return n + 42;
    }
};

struct Derived : Base { };

int foo(Derived& d, int n) {
    return d.bar(n);
}

becomes-O1:

foo(Derived&, int):
        lea     eax, [rsi+42]
        ret

而没有 final,我们得到一个间接调用:

foo(Derived&, int):
        sub     rsp, 8
        mov     rax, QWORD PTR [rdi]
        call    [QWORD PTR [rax]]
        add     rsp, 8
        ret