Is there any reason to specify a function as final
when the class is already final
? Or is that redundant?
class B
{
public:
virtual void f();
};
class D final : public B
{
public:
virtual void f() final; // Redundant final?
};
Would it be a good rule of thumb to say: Start with making the whole class final
, and only switch to making individual functions final
when you need to derive from the class and/or override specific functions?
It is definitely redundant because marking whole class as
final
makes it impossible to derive from this class and therefore override anything.So compiler won't even bother to check whether class deriving from
final
class actually tries to override anything or not.No, it is not redundant, because
final
means different things when applied to classes and methods.When
final
is applied to a class, it means that the class may not appear in the base-specifier-list of another class (i.e. you can't inherit from it)When
final
is applied to a member function, it means that the function must be virtual in an ancestor class, and further specifies that it may not be overridden in a descendant class.The key distinction is that
final
on a member function says that you must be overriding a virtual method in an ancestor class- if you're not, the compiler throws an error. When applied to a member function,final
is basically an extension of theoverride
keyword.Applying
final
to methods can be very helpful in catching subtle bugs that would not be caught if you only specifyfinal
on the class.Example 1: If you have misspelled the function name, or have not perfectly reproduced the parameter list, the function isn't actually overriding the base function and isn't going to be called when you think it's going to be called. But if you have specified that the function is
final
(oroverride
) the compiler will detect that you are not successfully overriding a base function, and will throw an error. If you have only specified that the class isfinal
, the compiler won't care that your function isn't actually overriding a virtual function, and won't throw an error.Example 2: If you specify that a member function is
final
and the function signature in the base class changes (e.g. someone makes changes to the base class after you've tested and checked in your code), the compiler will helpfully point out that the base function is no longer being overridden by your function.