Consider a program that has a class Foo
containing a function Foo::fn
declared like this:
virtual void fn();
and
If fn
is defined as final
in Bar
, the compiler can dispatch calls to fn
through a pointer or reference to Bar
statically since it knows that Bar::fn
is the final overrider. For example, this program fragment:
struct Foo {
virtual void fn();
};
struct Bar : Foo {
void fn() final override;
};
void with_foo(Foo& o) { o.fn(); }
void with_bar(Bar& o) { o.fn(); }
compiles to (See gcc.godbolt.org for details):
with_foo(Foo&):
subq $8, %rsp
movq (%rdi), %rax
call *(%rax)
addq $8, %rsp
ret
with_bar(Bar&):
subq $8, %rsp
call Bar::fn()
addq $8, %rsp
ret
the call in with_foo
is dynamically dispatched (call *(%rax)
is an indirect call) through the vtable, but the call in with_bar
statically dispatches to Bar::fn()
.
The simplest method to make Bar::fn
be the final overrider of Foo::fn
without changing behavior is to define it to statically call Foo::fn
:
struct Bar : Foo {
void fn() final override { Foo::fn(); }
};