What's the point of a final virtual function?
Wikipedia has the following example on the C++11 final modifier:
struct Base2 {
virtual void f() final;
};
struct Derived2 : Base2 {
void f(); // ill-formed because the virtual function Base2::f has been marked final
};
I don't understand the point of introducing a virtual function and immediately marking it as final. Is this simply a bad example, or is there more to it?
Typically final
will not be used on the base class' definition of a virtual function. final
will be used by a derived class that overrides the function in order to prevent further derived types from further overriding the function. Since the overriding function must be virtual normally it would mean that anyone could override that function in a further derived type. final
allows one to specify a function which overrides another but which cannot be overridden itself.
For example if you're designing a class hierarchy and need to override a function, but you do not want to allow users of the class hierarchy to do the same, then your might mark the functions as final in your derived classes.
For a function to be labelled final
it must be virtual
, i.e., in C++11 §10.3 para. 2:
[...] For convenience we say that any virtual function overrides itself.
and para 4:
If a virtual function f in some class B is marked with the virt-specifier final and in a class D derived from B a function D::f overrides B::f, the program is ill-formed. [...]
i.e., final
is required to be used with virtual functions (or with classes to block inheritance) only. Thus, the example requires virtual
to be used for it to be valid C++ code.
EDIT: To be totally clear: The "point" asked about concerns why virtual is even used. The bottom-line reason why it is used is (i) because the code would not otherwise compile, and, (ii) why make the example more complicated using more classes when one suffices? Thus exactly one class with a virtual final function is used as an example.
It doesn't seem useful at all to me. I think this was just an example to demonstrate the syntax.
One possible use is if you don't want f to really be overrideable, but you still want to generate a vtable, but that is still a horrible way to do things.
I don't understand the point of introducing a virtual function and immediately marking it as final.
The purpose of that example is to illustrate how final
works, and it does just that.
A practical purpose might be to see how a vtable influences a class' size.
struct Base2 {
virtual void f() final;
};
struct Base1 {
};
assert(sizeof(Base2) != sizeof(Base1)); //probably
Base2
can simply be used to test platform specifics, and there's no point in overriding f()
since it's there just for testing purposes, so it's marked final
. Of course, if you're doing this, there's something wrong in the design. I personally wouldn't create a class with a virtual
function just to check the size of the vfptr
.
Adding to the nice answers above - Here is a well-known application of final (very much inspired from Java). Assume we define a function wait() in a Base class, and we want only one implementation of wait() in all its descendants. In this case, we can declare wait() as final.
For example:
class Base {
public:
virtual void wait() final { cout << "I m inside Base::wait()" << endl; }
void wait_non_final() { cout << "I m inside Base::wait_non_final()" << endl; }
};
and here is the definition of the derived class:
class Derived : public Base {
public:
// assume programmer had no idea there is a function Base::wait()
// error: wait is final
void wait() { cout << "I am inside Derived::wait() \n"; }
// that's ok
void wait_non_final() { cout << "I am inside Derived::wait_non_final(); }
}
It would be useless (and not correct) if wait() was a pure virtual function. In this case: the compiler will ask you to define wait() inside the derived class. If you do so, it will give you an error because wait() is final.
Why should a final function be virtual? (which is also confusing) Because (imo) 1) the concept of final is very close to the concept of virtual functions [virtual functions has many implementations - final functions has only one implementation], 2) it is easy to implement the final effect using vtables.