Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should classes with public non-virtual destructors be marked "final"? [closed]

Tags:

c++

c++11

To close voters, please help me improve the question so it gets reopened: How can I improve this question so that it gets reopened?

Herb Sutter wrote:

A base class destructor should be either public and virtual, or protected and nonvirtual.

According to that guideline, if you have a class with a public non-virtual destructor, then that class shouldn't be used as a base class. Why not mark it final to enforce that?


But Sutter also wrote the following, implying that final need not be used:

Re "uses of final are rarer" - well, they sort of are. I don’t know of many, and during standardization Bjarne repeatedly asked for examples of problems it solved and patterns where it should be used, and I don’t recall any major ones that stood out.

Another relevant quote, implying that final should be used now that it's available, is from Scott Meyer's Effective C++, item 7:

If you're ever tempted to inherit from a standard container or any other class with a non-virtual destructor, resist the temptation! (Unfortunately, C++ offers no derivation-prevention mechanism akin to Java's final classes or C#'s sealed classes.)

Another data point is that the standard library has no types marked "final", but the reason for that seems to be to avoid breaking code.

There's a similar question here, but not exactly a duplicate as it misses the "protected, nonvirtual" option: Default to making classes either `final` or give them a virtual destructor?

like image 501
Jon Avatar asked Aug 04 '15 13:08

Jon


People also ask

What happens if destructor is not virtual?

Deleting a derived class object using a pointer of base class type that has a non-virtual destructor results in undefined behavior.

Should virtual destructors be marked override?

As long as the base class has the destructor marked as virtual, all derived class destructors will call the basal destructor correctly. In your case it doesn't matter much. But just in case you're actually using virtual functions yourself in your other classes, you should stick with the override keyword.

When should you mark a destructor as virtual?

Here's a simplified rule of thumb that usually protects you and usually doesn't cost you anything: make your destructor virtual if your class has any virtual functions. Rationale: that usually protects you because most base classes have at least one virtual function.

Why should destructors be declared virtual?

Virtual destructors in C++ are used to avoid memory leaks especially when your class contains unmanaged code, i.e., contains pointers or object handles to files, databases or other external objects. A destructor can be virtual.


2 Answers

According to that guideline, if you have a class with a public non-virtual destructor, then that class shouldn't be used as a base class. Why not mark it final to enforce that?

Because it's a guideline that fits in certain situations, but not all, so why would you "enforce" it?

It's all very well and good disallowing inheritance where dynamic polymorphism through virtual function calls has not been provisioned, but that's not the only scenario in which we use inheritance.

C++ is multi-paradigm and it doesn't make sense to start enforcing narrow approaches that fit only a subset of use cases. Your suggestion, from what I can tell, essentially boils down to prohibiting people from using inheritance unless they're also going to use dynamic polymorphism.

like image 95
Lightness Races in Orbit Avatar answered Sep 28 '22 12:09

Lightness Races in Orbit


I routinely declare classes as final unless they are

  • intended to be used as base classes or
  • POD types.

I think it is a good thing to explicitly design for inheritance (which should be used sparingly after all). And if I didn't bother designing a class as a base class, I document this by declaring it final. If later I find that it would be useful to derive from that class, having to go and remove the final is a good opportunity to also check that the other conditions for making it a viable base class are met.

I usually don't declare POD types as final because I don't see any benefit in doing so and deriving from them is sometimes useful to utilize the empty base optimization.

like image 24
5gon12eder Avatar answered Sep 28 '22 13:09

5gon12eder