A base class in C++ should have at least a virtual
destructor, if I inherit from the class. Therefore, one should e.g. better not inherit from std::optional
.
The answer here says
If it doesn't have any virtual methods, then you shouldn't be using it as a base. This rules out std::vector and the like.
If I can't safely inherit from std::optional
or std::vector
, I expect them to be final
. That sounds like this keyword was made exactly for this purpose.
Specifies that [...] a class cannot be derived from.
If we ignore the advise, it seems we get undefined behavior when deriving from such classes.
There's even core guideline C.139, "Use final on classes sparingly". And that guideline confirms:
Not every class is meant to be a base class. Most standard-library classes are examples of that (e.g., std::vector and std::string are not designed to be derived from).
IMHO, using final
on such classes would prevent problems.
For which scenario do I need the non-final-ness of std::
-classes?
A base class in C++ should have at least a virtual
destructor, if I inherit from the class. Therefore, one should e.g. better not inherit from std::optional
.
The answer here says
If it doesn't have any virtual methods, then you shouldn't be using it as a base. This rules out std::vector and the like.
If I can't safely inherit from std::optional
or std::vector
, I expect them to be final
. That sounds like this keyword was made exactly for this purpose.
Specifies that [...] a class cannot be derived from.
If we ignore the advise, it seems we get undefined behavior when deriving from such classes.
There's even core guideline C.139, "Use final on classes sparingly". And that guideline confirms:
Not every class is meant to be a base class. Most standard-library classes are examples of that (e.g., std::vector and std::string are not designed to be derived from).
IMHO, using final
on such classes would prevent problems.
For which scenario do I need the non-final-ness of std::
-classes?
- 5 You can inherit from non-virtual base-classes, but you can't use the new classes in a polymorphic way. – Some programmer dude Commented Nov 19, 2024 at 17:34
- 1 FWIW private inheritance removes many/all of the issues of inheriting non virtual base classes. IMHO it comes down to if the class should be an interface or not. If yes, then use virtual at least for the destructor and final on the final derived classes. If non then don't use virtual or final – NathanOliver Commented Nov 19, 2024 at 17:34
- 2 There's nothing inherently wrong with deriving from a base class that has no virtual functions. The true rule is that if your design calls for deleting objects of a derived type through pointers to the base, then the base must have at least one virtual function. – Pete Becker Commented Nov 19, 2024 at 17:47
- 1 @ThomasWeller -- it's your job to define and document what your class can and can't do. If somebody doesn't read your documentation and misuses your class that's on them. – Pete Becker Commented Nov 19, 2024 at 17:54
- 1 @ThomasWeller correct, they were not designed to be an interface. – NathanOliver Commented Nov 19, 2024 at 18:03
1 Answer
Reset to default 5It is perfectly fine to use these classes like std::vector
as base class.
You just have to know what deriving from a class without virtual destructor means, namely that you can't pass ownership to it via base class reference/pointer.
And you have to be aware what especially public inheritance means if the standard library extends or changes the classes' interface and that it enables implicit conversion to base class pointers/references.
Of course, also, because the functions in the base class are not virtual
you can't pretend that they are and expect e.g. a member function call on a base class reference to call your implementation in the derived class. But that is obvious and applies to every non-virtual
function call in every class. (And non-virtual
should be the default. Making all functions virtual
for no reason would be horrible.) I.e. you can't treat the derived class as an implementation or extension of some abstract interface that the standard library base class implements.
Otherwise there is no UB or anything prohibiting the use of standard library classes as base class or any problem with doing so.
All of this applies exactly the same to any other class without virtual destructor or with other non-virtual
functions and a general rule prohibiting inheritance from classes without virtual destructor is IMO way too strict. Consider for example aggregate classes with base classes or common implementations of std::tuple
and such which rely on inheritance for completely different reasons than polymorphism.
A rule requiring that every base class have only a purely virtual
interface would be even worse. Use OOP principles strictly where it makes sense, but C++ is not fundamentally built on them and most of the standard library for example does not follow OOP principles strictly. Using such a approach is especially detrimental to performance, which is usually the number one reason to use C++ over other high-level languages.
For example I do not see much wrong with e.g. deriving from std::vector
, also publicly, if the goal is just to add some custom member functions for convenience and there is never an attempt made by the user to destroy the class through a pointer/reference to std::vector
. The extra member function wouldn't invalidate use of any of the other member functions, also through a base class pointer/reference, so there is no problem with this.
The worst that could happen is that a future standard version will use the custom member function name for a different functionality.
Even if there was a policy to prohibit deriving from standard library classes, final
was added only with C++11 and because there was no prohibition on deriving in earlier C++ versions, adding final
to standard library classes now would be a breaking change in the language.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1742410247a4438667.html
评论列表(0条)