isocpp / CppCoreGuidelines

The C++ Core Guidelines are a set of tried-and-true guidelines, rules, and best practices about coding in C++
http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines
Other
42.46k stars 5.43k forks source link

C128: Unclear about the preference in a final class #1574

Closed JVApen closed 4 years ago

JVApen commented 4 years ago

The following rule states: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c128-virtual-functions-should-specify-exactly-one-of-virtual-override-or-final

Use either virtual, override or final.

However, it doesn't indicate a preference to use in the following case:

class I { void f() = 0; }; class A final : public I { virtual void f() override final {} };

Does this rule imply we should make A::f() override or final? (With A being a final class)

szaszm commented 4 years ago

Since final can only be applied to virtual functions, if you follow the rule by not marking a function virtual on the same line where you mark it final, then final will cause a compile-time error if there is no matching virtual function declared in the base class. [1] This behavior makes override redundant.

The rule states, that override means non-final overrider, while final means final overrider. In your example, A::f() is a final overrider, therefore you should use final and not override or virtual.

[1] https://godbolt.org/z/dKLFqr

JVApen commented 4 years ago

So if I understand you correctly you prefer class I { void f() = 0; }; class A final : public I { void f() final {} }; over class I { void f() = 0; }; class A final : public I { void f() override {} };? This feels uncomfortable to me, whats the point of the final identifier on the class level in that case?

szaszm commented 4 years ago

Yes. That's how I understand the guideline and I prefer to follow it.

The final on the class prevents subclassing, while the final on the virtual functions prevent further overriding. While final on the class implies that, it also says more. In these classes, final on virtual functions is equivalent to override, but is harmless, makes local reasoning (e.g. in diffs) easier and makes it possible to follow this useful guideline without thinking, i.e. freeing up mental resources for important things.

hsutter commented 4 years ago

Editors call: We'll add a cross-reference to C.139 and note that it doesn't matter whether a function is declared with override or final if the whole class is already final.