Derived class with non-virtual destructor

C++

C++ Problem Overview


Are there any circumstances in which it is legitimate for a derived class to have a non-virtual destructor? A non-virtual destructor signifies that a class should not be used as a base-class. Will having a non-virtual destructor of a derived class act like a weak form of the Java final modifier?

I am especially interested in the case where the base class of the derived class has a virtual destructor.

C++ Solutions


Solution 1 - C++

> Are there any circumstances in which it is legitimate for a derived > class to have a non-virtual destructor?

Yes.

> A non-virtual destructor signifies that a class should not be used as > a base-class.

Not really; a non-virtual destructor signifies that deleting an instance of derived via a base pointer will not work. For example:

class Base {};
class Derived : public Base {};

Base* b = new Derived;
delete b; // Does not call Derived's destructor!

If you don't do delete in the above manner, then it will be fine. But if that's the case, then you would probably be using composition and not inheritance.

> Will having a non-virtual destructor of a derived class act like a > weak form of the Java final modifier?

No, because virtual-ness propagates to derived classes.

class Base
{
public:
    virtual ~Base() {}
    virtual void Foo() {};
};

class Derived : public Base
{
public:
    ~Derived() {}  // Will also be virtual
    void Foo() {}; // Will also be virtual
};

There isn't a built-in language mechanism in C++03 or earlier to prevent subclasses(*). Which isn't much of an issue anyway since you should always prefer composition over inheritance. That is, use inheritance when a "is-a" relationship makes more sense than a true "has-a" relationship.

(*) 'final' modifier was introduced in C++11

Solution 2 - C++

It is perfectly valid to have an Base class with an non virtual destructor if you are never going to call delete on a Base class pointer pointing to an derived class object.

Follow Herb Sutter's Advice:

Guideline #: Only if derived classes need to invoke the base implementation of a virtual function, make the virtual function protected. For the special case of the destructor only:

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


Maybe your question actually is:
Does Destructor in Derived class needs to be virtual if Base class Destructor is virtual?

The answer is NO.
If Base class destructor is virtual then the Derived class destructor is implicitly virtual already, you don't need to specify it as virtual explicitly.

Solution 3 - C++

Addresssing the latest edit:

> Edit: I am especially interested in the case where the base class of the derived class has a virtual destructor.

In that case, the destructor of the derived class will be virtual, regardless of whether you add the virtual keyword or not:

struct base {
   virtual ~base() {}       // destructor is virtual
};
struct derived : base {
   ~derived() {}            // destructor is also virtual, because it is virtual in base
};

This is not limited to destructors, if at any point in a type hierarchy a function member is declared virtual, all overrides (not overloads) of that same function will be virtual, whether they are declared as so or not. The specific bit for destructors is that ~derived() overrides virtual ~base() even if the name of the member differs --that is the only specificity for destructors here.

Solution 4 - C++

You're question isn't really clear. If the base class has a virtual destructor, the derived class will have one, regardless. There's no way to turn virtuality off, once it's been declared.

And there are certainly cases where it makes sense to derive from a class which doesn't have a virtual destructor. The reason why the base class destructor should be virtual is so that you can delete through a pointer to the base class. If the derivation is private, you don't have to worry about this, since your Derived* won't convert to a Base*. Otherwise, I've seen the recommendation that if the base class destructor isn't virtual, it should be protected; this prevents the one case of undefined behavior (deleting through a pointer to base) that could occur. In practice, however, a lot of base classes (e.g. std::iterator<>) have semantics such that it doesn't even occur to anyone to create pointers to them; much less delete through such pointers. So adding the protection may be more effort than it's worth.

Solution 5 - C++

Depends on the purpose of your class. Sometimes it is a good practice to make your destructor protected, but not virtual - that basically says: "You shall not delete an object of derived class via a base-type pointer"

Solution 6 - C++

If your derived class doesn't add any data members to the base class, and has an empty destructor body, then it won't matter if the destructor is virtual or not - all the derived destructor will do is call the base one anyway. It isn't recommended because it's far too easy for someone to come along and modify the class without being aware of these restrictions.

If you never try to delete an object through a pointer to the base class, you'll be safe. This is another rule that's hard to enforce and should be used with care.

Sometimes you don't have any control over the base class and you're forced to derive from it, even though the destructor isn't virtual.

Finally, having a non-virtual destructor in the base class doesn't impose any restriction on the derived class that will be enforced by the compiler, so I don't think it resembles Java's final at all.

Solution 7 - C++

A non-virtual destructor is perfectly fine as long as you you don't want to use it as a base pointer for derived classes when deleting the object.

If you its derived classes in a polymorphic way, passing and storing it with a base pointer and then deleting it then the answer is no, use a virtual destructor.

Solution 8 - C++

Yes, there are:

void dothis(Base const&);

void foo() {
  Derived d;
  tothis(d);
}

Here the class is used polymorphically, yet delete is not called, thus it's fine.

Another example would be:

std::shared_ptr<Base> create() { return std::shared_ptr<Base>(new Derived); }

because a shared_ptr is able to use a non-polymorphic delete (through type erasure).

I implemented a warning in Clang specifically to detect the call of delete on polymorphic non-final classes with non-virtual destructors, so if you use clang -Wdelete-non-virtual-dtor, it will warn specifically for this case.

Solution 9 - C++

Yes, No and No.

Virtual destructor has nothing to do with ability of the class to be a base or a derived class. It is a legitimate one as both.

However, there are certain reasons to make destructors virtual. See here: http://en.wikipedia.org/wiki/Virtual_destructor#Virtual_destructors . This makes a class, among other things, have a virtual table if it doesn't have one already. However, virtual tables are not required by C++ to do inheritance.

Solution 10 - C++

> Will having a non-virtual destructor of a derived class act like a weak form of the Java final modifier?

Not at all. Here is my suggestion to prevent sub classes in C++ (like final modifier in Java); make the destructor private in a class. Then you can prevent making sub-classes from it

Solution 11 - C++

You may not want to create virtual destructor in base class? No destructor do in this case. If you use pointer to base class and create non-virtual destructor in parent one compilator automatically generate this warning! You may block it if you want to create final parent class. But best is to mark it as a final like:

class Base{
public:
    //No virtual destructor defined
    virtual void Foo() {};
};

class Derived final : public Base{
public:
    ~Derived() {}  // define some non-virtual destructor
    void Foo() {}; // Will also be virtual
};

In this case compilator knows what you want and no warnings generate. The decision with empty virtual base destructor is not too well but acceptable. You needn't set attribute final. But this isn't the thing you want.You also needn't define empty virtual base method Foo too Best is:

class Base{
public:
  //No virtual destructor defined
  virtual void Foo() = 0; // abstract method
};
class Derived final : public Base{
public:
  ~Derived() {}  // define some non-virtual destructor
  void Foo() {}; // Will also be virtual
};

It's full clear code for compilator. No warnings generate and no spare code used too.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRaedwaldView Question on Stackoverflow
Solution 1 - C++In silicoView Answer on Stackoverflow
Solution 2 - C++Alok SaveView Answer on Stackoverflow
Solution 3 - C++David Rodríguez - dribeasView Answer on Stackoverflow
Solution 4 - C++James KanzeView Answer on Stackoverflow
Solution 5 - C++Nemanja TrifunovicView Answer on Stackoverflow
Solution 6 - C++Mark RansomView Answer on Stackoverflow
Solution 7 - C++Karoly HorvathView Answer on Stackoverflow
Solution 8 - C++Matthieu M.View Answer on Stackoverflow
Solution 9 - C++Pavel RadzivilovskyView Answer on Stackoverflow
Solution 10 - C++SRFView Answer on Stackoverflow
Solution 11 - C++tolyaView Answer on Stackoverflow