2

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.

Community
  • 1
  • 1
Carlton
  • 4,217
  • 2
  • 24
  • 40

1 Answers1

3

Yes!

Speaking practically...

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() {}
};

Speaking legally...

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.

Speaking verifiably...

Ultimately, though, the only way to be sure is to actually examine the code that your compiler produces.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • In the post I referenced, another user mentioned that `dynamic_cast` probably relies on virtual tables, so eliding the vtable would break `dynamic_cast` (for better or for worse). – Carlton Apr 02 '15 at 13:20
  • I think the "no base" situation is similar to the "base, but not a polymorphic base" situation. – MSalters Apr 02 '15 at 13:48