在这篇文章中:Does final imply override?,其中一个答案显示您可以在同一声明中声明函数virtual
和final
。给出了一个例子,它可以防止派生类错误地声明具有相同签名的函数,从而避免混淆实际调用哪个函数。
我的问题是,编译器是否仍会为这样的函数生成虚拟表?如果我知道我没有引起vtable运行时开销,我会更频繁地使用这种技术。
答案 0 :(得分:3)
首先,不为函数生成虚拟表;为类型生成虚拟表(每个实例都有一个指向相关虚拟表的指针)。
仅仅因为没有一个函数成员可以被进一步覆盖而忽略整个虚拟表会导致大量问题;例如,当通过指向final
的引用引用实例时,生成的二进制文件仍然需要能够查找 Base
类型。
唯一可能有意义的是带有虚拟成员的类型,它们都是final
,且没有基础:
/**
* No members override (as there's no base)
* and no members may be overridden (as they're
* all `final`).
*/
struct Foo
{
virtual void foo() final {}
};
编译器是否会忽略虚拟表?也许。可能不是;为什么要为极端角落场景实现替代的,特殊情况的语义集?
实际上,当你稍后在层次结构中进一步添加新的虚拟成员时,它可能会在一般情况下破坏:
/**
* Well, this one needs a virtual table...
* ...and it's probably going to want to
* point out where Foo::foo() is...?
*/
struct Bar : Foo
{
virtual void bar() {}
};
除此之外,我无法看到任何证据表明虚拟表格符合ABI标准,至少不在Itanium下:
具有虚拟成员函数或虚拟基础的每个类都有一组关联的虚拟表。
final
说明符是一个C ++构造仅,没有ABI支持,禁止这种魔法。
但最终,确定的唯一方法是实际检查编译器生成的代码。