13

I have

struct IMyInterface
{
   virtual method1() = 0;
   virtual method2() = 0;
};

GCC insists that I have

struct IMyInterface
{
   virtual method1() = 0;
   virtual method2() = 0;
   virtual ~IMyInterface(){};
};

I dont see why. A pure interface is all about the interface (duh). The destructor is part of the internal implementation details of a concrete implementer of the interface; it does not form part of the interface. I understand the whole slicing issue (or at least I think I do)

So my question is - is GCC right to insist on it and if so why?

j0k
  • 22,600
  • 28
  • 79
  • 90
pm100
  • 48,078
  • 23
  • 82
  • 145
  • You are talking about destructors, but your code shows a constructor. Which is the question about? – Michael Myers Jul 26 '10 at 15:51
  • 1
    Rule 1 of Programming: The Compiler is Always Right. Rule 2 of Programming: If the Compiler is Wrong, Rule 1 Applies. – Brian Hooper Jul 26 '10 at 16:03
  • You can have a pure virtual destructor (`virtual ~IMyInterface() = 0;`) but if the linker complains about a missing definition, you can actually still provide implementations for pure virtual functions, ie. `virtual ~IMyInterface() = 0 {}`. – AshleysBrain Jul 26 '10 at 19:51

2 Answers2

25

According to the C++ spec, yes.

You need to declare the destructor virtual because otherwise, later

    IMyInterface * ptr = getARealOne();
    delete ptr;

won't call the destructor on the derived class (because the destructor isn't in the VTable)

It needs to be non-pure because base class destructors are always called by the sub-class destructor.

To further explain, C++ doesn't have a concept of an interface in the same way that Java or C# do. It's just a convention to use only pure-virtual methods, and think of that as an interface. The other rules about C++ destructors make it need to be non-pure, which breaks the similarity to interfaces in other languages, but those languages didn't exist at the time these rules were made.

Lou Franco
  • 87,846
  • 14
  • 132
  • 192
  • 4
    Nitpick - I think you can make it pure virtual if you want to require child classes to implement it. But you still have to provide an implementation for the reasons you stated. – Michael Kristofik Jul 26 '10 at 15:54
  • I don't think so -- it will be called, so it better have a definition. I haven't tried it, but usually a pure-virtual is implemented by the compiler as putting an error function in the VTable to complain that it was called. Perhaps I could imagine a special case for destructors, but I'm pretty sure that that isn't what the spec says (Not 100% though) – Lou Franco Jul 26 '10 at 15:57
  • @Lou Franco: Pure virtual functions can have definitions. – Billy ONeal Jul 26 '10 at 16:01
  • @Lou: "pure" doesn't mean that it doesn't have a definition, just that it must be overridden. The destructor can be pure or not, but must have a definition. – Mike Seymour Jul 26 '10 at 16:02
  • Yes -- sorry, that's right. Not the way he's doing it (at the point of declaration). – Lou Franco Jul 26 '10 at 16:08
  • Here's the relevant part of the spec discussion http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#230 – Lou Franco Jul 26 '10 at 16:13
3

If you don't declare the virtual d'tor in the base class, deleting objects of derived classes through a pointer to the base class leads to the wrong destructor being called, and thus to undefined behaviour and resource leaking.

struct A {

  virtual ~A() {}

};

struct B : A {

   std::string us_constitution;  
};


B* pb = new B();
A* pa = pb;

delete pa; // without the virtual d'tor in the base class, 'B::us_constitution' would never be freed.
Alexander Gessler
  • 45,603
  • 7
  • 82
  • 122
  • Nitpick: B::us_constitution cannot be free'd because it was never new'd. The storage it uses, however, will not be returned to the system without the virtual destructor. – Billy ONeal Jul 26 '10 at 16:03