header image
[ # ] On Destructors and Interfaces in C++
September 11th, 2012 under Programming

Comming from Java, I’m used to use interfaces (abstract classes with only abstract virtual methods. In C++ we only have the concept of abstract classes which are classes with at least one pure virtual function) in my type hierarchy.

This concept of an interface does not exist nor can or should it be used in a “copy-paste” manner. Let me give an example.

In Java we define an interface as:

1
2
3
public interface Interface {
   void method(int arg);
}
public interface Interface {
   void method(int arg);
}

So every subclass of Interface must implement/override method. In C++ this would look as follows when we “copy-paste” this:

1
2
3
4
5
class Interface 
{
  public: 
    virtual void method(int arg) = 0;
};
class Interface 
{
  public: 
    virtual void method(int arg) = 0;
};

Now, the C++ class cannot, by definition, function as a proper interface/abstract class. The problem is caused by the (here implicit) non-virtual destructor. So, as a result we cannot use the Interface as a base type pointer when we delete the object.

1
2
Interface* p = new Subclass();
delete p;
Interface* p = new Subclass();
delete p;

here the behavior is undefined according to the C++ standard. Normally though it would just call the implicit non-virtual destructor

1
Interface::~Interface()
Interface::~Interface()
.

To fix this we can either define an empty virtual destructor or declare the destructor as impure virtual.

So either

1
2
3
4
5
6
class Interface 
{
  public: 
    virtual void method(int arg) = 0;
    virtual ~Interface(void) {}
};
class Interface 
{
  public: 
    virtual void method(int arg) = 0;
    virtual ~Interface(void) {}
};

or

1
2
3
4
5
6
class Interface 
{
  public: 
    virtual void method(int arg) = 0;
    virtual ~Interface(void) = 0;
};
class Interface 
{
  public: 
    virtual void method(int arg) = 0;
    virtual ~Interface(void) = 0;
};

In the second case, it would be impossible to instantiate a subclass because the destructor of the subclass calls the destructor of its parents. Meaning

1
Interface::~Interface
Interface::~Interface
would be called but does not exists. Hence, it would result in an undefined reference error. A solution to this is to use an impure destructor [1]. This means we leave the pure virtual declaration of the destructor but still provide an implementation in the cpp file.

But in any case you must to tell the compiler that you want the destructor to be virtual.

References:
[1] http://www.gotw.ca/gotw/031.htm