In this post: Does final imply override?, one of the answers showed that you can declare a function virtual
AND final
in the same declaration. An example was given that this prevents derived classes from mistakenly declaring a function with the same signature, so as to avoid confusion about which function is actually being called.
My question is, will a compiler still generate a virtual table for such a function? I would use this technique more often if I knew I wasn't incurring the vtable runtime overhead.
Firstly, virtual tables are not generated for functions; virtual tables are generated for types (with each instance having a pointer to the relevant virtual table).
Eliding the entire virtual table for a type just because none of its function members can be further overridden would cause a wealth of problems; for example, the resulting binary still needs to be able to find that final
type when the instance is referenced through a pointer-to-Base
.
The only time this may make sense is with a type with virtual members, which are all final
, and no base:
/**
* 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 {}
};
Does a compiler elide the virtual table then? Maybe. Probably not; why implement an alternative, special-case set of semantics for an extreme corner scenario?
Actually, it would probably break anyway in the general case when you later add new virtual members further up the hierarchy:
/**
* 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() {}
};
Besides all this, I can't see any evidence that eliding the virtual table would be ABI-compliant, at least not under Itanium:
Each class that has virtual member functions or virtual bases has an associated set of virtual tables.
The final
specifier is a C++ construct only with no ABI support, prohibiting such magic.
Ultimately, though, the only way to be sure is to actually examine the code that your compiler produces.