Why Do We Need a Pure Virtual Destructor in C++

Why do we need a pure virtual destructor in C++?

  1. Probably the real reason that pure virtual destructors are allowed is that to prohibit them would mean adding another rule to the language and there's no need for this rule since no ill-effects can come from allowing a pure virtual destructor.

  2. Nope, plain old virtual is enough.

If you create an object with default implementations for its virtual methods and want to make it abstract without forcing anyone to override any specific method, you can make the destructor pure virtual. I don't see much point in it but it's possible.

Note that since the compiler will generate an implicit destructor for derived classes, if the class's author does not do so, any derived classes will not be abstract. Therefore having the pure virtual destructor in the base class will not make any difference for the derived classes. It will only make the base class abstract (thanks for @kappa's comment).

One may also assume that every deriving class would probably need to have specific clean-up code and use the pure virtual destructor as a reminder to write one but this seems contrived (and unenforced).

Note: The destructor is the only method that even if it is pure virtual has to have an implementation in order to instantiate derived classes (yes pure virtual functions can have implementations).

struct foo {
virtual void bar() = 0;
};

void foo::bar() { /* default implementation */ }

class foof : public foo {
void bar() { foo::bar(); } // have to explicitly call default implementation.
};

Why a pure virtual destructor needs an implementation

The compiler tries to build the virtual table given a virtual (pure or not) destructor, and it complains because it can't find the implementation.

virtual destructors differ from other virtual functions because they are called when the object is destroyed, regardless of whether it was implemented or not. This requires the compiler to add it to the vf table, even if it's not called explicitly, because the derived class destructor needs it.

Pedantically, the standard requires a pure virtual destructor to be implemented.

Why must a pure virtual destructor's implementation be empty? And should it be inline?

A pure virtual destructor must have an implementation (assuming you have at least one concrete derived class).

There is no rule that a pure virtual destructor must have empty body. Nor do I know of any reason that it should, except the same reasons most destructors should have an empty body.

A pure virtual destructor can be inline or non-inline. I would expect the benefits of each to depend on the number of base classes and non-static members with non-trivial destructors.

One other catch, though: on certain popular compilers, if the destructor is the only virtual method defined for the class, it is a good idea to make it non-inline, to help the implementation deal with its polymorphism magic.

why we are not obliged to implement pure virtual destructor?

why we are not obliged to implement the pure virtual base's destructor in our derived class?

Because destructors are not overridden.

To help remember that, think about the names: ~Base and ~Derived are not the same. Constructors and destructors, instead of working through overriding, are instead called in a chain: the bottom-most destructor runs and then it calls its parent destructor which then runs and then calls its parent destructor etc.

And that is why you must provide the body for a destructor if you want to delete an instance of one of the derived classes, even if it's marked as pure virtual: it needs a body to invoke when reaching it in the destructor chain.

So, what's the deal with virtual destructors to start with? It's done so that the compiler would know to invoke the bottom-most destructor when it encounters a destruction of some class. So destruction does use the virtual table, it's just that it's running the parent class destructor after the derived destructor is done, so it's not standard overriding.

does it mean as long as C++ adds to us four member functions by default: constructor, copy constructor, assignment and Destructor we don't need to implement it in our derived class?

Didn't quite understand the question, but in any case default-added methods are not created pure virtual and can be created in every class in an inheritance chain.

When to use virtual destructors?

Virtual destructors are useful when you might potentially delete an instance of a derived class through a pointer to base class:

class Base 
{
// some virtual methods
};

class Derived : public Base
{
~Derived()
{
// Do some important cleanup
}
};

Here, you'll notice that I didn't declare Base's destructor to be virtual. Now, let's have a look at the following snippet:

Base *b = new Derived();
// use b
delete b; // Here's the problem!

Since Base's destructor is not virtual and b is a Base* pointing to a Derived object, delete b has undefined behaviour:

[In delete b], if the static type of the
object to be deleted is different from its dynamic type, the static
type shall be a base class of the dynamic type of the object to be
deleted and the static type shall have a virtual destructor or the
behavior is undefined
.

In most implementations, the call to the destructor will be resolved like any non-virtual code, meaning that the destructor of the base class will be called but not the one of the derived class, resulting in a resources leak.

To sum up, always make base classes' destructors virtual when they're meant to be manipulated polymorphically.

If you want to prevent the deletion of an instance through a base class pointer, you can make the base class destructor protected and nonvirtual; by doing so, the compiler won't let you call delete on a base class pointer.

You can learn more about virtuality and virtual base class destructor in this article from Herb Sutter.

Pure virtual destructor in C++

Yes. You also need to implement the destructor:

class A {
public:
virtual ~A() = 0;
};

inline A::~A() { }

should suffice.

And since this got a down vote, I should clarify: If you derive anything from A and then try to delete or destroy it, A's destructor will eventually be called. Since it is pure and doesn't have an implementation, undefined behavior will ensue. On one popular platform, that will invoke the purecall handler and crash.

Edit: fixing the declaration to be more conformant, compiled with http://www.comeaucomputing.com/tryitout/

C++11 interface pure virtual destructor

The difference between I1 and I2*, as you pointed out, is that adding = 0 makes the class abstract. In fact, making the destructor pure virtual is a trick to make a class abstract when you don't have any other function to be pure virtual. And I said it's a trick because the destructor cannot be left undefined if you ever want to destruct any derived class of it (and here you will), then you still need to define the destructor, either empty or defaulted.

Now the difference between empty or defaulted destructor/constructor (I21 and I22) is way more obscure, there isn't much written out there. The recommended one is to use default, both as a new idiom to make your intentions clearer, and apparently, to give the compiler a chance for optimization. Quoting msdn

Because of the performance benefits of trivial special member functions, we recommend that you prefer automatically generated special member functions over empty function bodies when you want the default behavior.

There are no visible differences between the two, apart from this possible performance improvement. = default is the way to go from C++11 on.

What is the purpose of pure virtual destructor?

Sometimes an abstract base class has no virtual methods (= often called a “mixin”) or no methods at all (= often called a “type tag”).

To force those classes to be used as abstract base classes, at least one method needs to be pure virtual – but the classes don’t have virtual methods! So we make the destructor pure virtual instead.

virtual destructor for pure abstract class

My question is it absolutely must that we define a virtual destructor for "Base" class, even though it does have any data members?

It depends. If you have a case like

base * foo = new child(stuff);
// doing stuff
delete foo;

then you absolutely must have a virtual destructor. Without it you'll never destroy the child part.

If you have a case like

child * foo = new child(stuff);
// doing stuff
delete foo;

Then you do not need a virtual destructor, as child's will be called.

So the rule is if you delete polymorphically, you need a polymorphic (virtual) destructor, if not, then you don't



Related Topics



Leave a reply



Submit