Consider a program that has a class Foo
containing a function Foo::fn
declared like this:
virtual void fn();
and a subclass of Foo
called Bar
. Will declaring Bar::fn
like this:
virtual void fn() override final;
cause calls to fn
in Bar
or subclasses of Bar
to be any more efficient, or will it just keep subclasses of Bar
from overriding fn
? If calls are made more efficient using final
, what is the simplest, most efficient method to define Bar::fn
such that its functionality is exactly that of Foo::fn
?
If
fn
is defined asfinal
inBar
, the compiler can dispatch calls tofn
through a pointer or reference toBar
statically since it knows thatBar::fn
is the final overrider. For example, this program fragment:compiles to (See gcc.godbolt.org for details):
the call in
with_foo
is dynamically dispatched (call *(%rax)
is an indirect call) through the vtable, but the call inwith_bar
statically dispatches toBar::fn()
.The simplest method to make
Bar::fn
be the final overrider ofFoo::fn
without changing behavior is to define it to statically callFoo::fn
:I've not EVER cared about the size of the vtable. It is typically relatively small, and there is only one per class declaration. What is much more bothersome is extra space taken up in the class instances, since, except for singleons, class instances are often many of. So adding extra elements into a class, in some way or another, will definitely affect the amount of memory. If it's REALLY bothering you that the vtable is too large, then doing some redesign so that there aren't so many different virtual member functions (perhaps splitting the class hierarchy into several classes) or fewer derived classes. But really, even if you have hundreds of classes, each with a hundred virtual member functions, it's still relatively small - 200 classes with 100 members would take up 20000 * 8 bytes per entry [64-bit architecture] -> 160KB. Surely the 20000 functions [yes, in theory, you only need ONE new function per derived class to need a new vtable, but that is rather a silly design, so unlikely in reality]
The purpose of the
final
keyword is to ensure that you don't derive from it further - this is useful for example if you have a basic class hierarchy where some particular function should not be "changed". Say for example you have:You have to trick around a bit to ensure that
user_base
isn't used as a base-class for afake_super_user
, and of course, there are other BIG security issues with such a design, but it gives you some idea.