c++ - In which scenario are non-final non-virtual classes like std::-classes useful? - Stack Overflow

A base class in C++ should have at least a virtual destructor, if I inherit from the class. Therefore,

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?

Share Improve this question asked Nov 19, 2024 at 17:29 Thomas WellerThomas Weller 59.8k23 gold badges137 silver badges253 bronze badges 11
  • 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
 |  Show 6 more comments

1 Answer 1

Reset to default 5

It 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条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信