Search code examples
c++visual-c++declspec

Behaviour of delete on novtable base class without a virtual destructor


As I understand it, if you call delete on an interface pointer (or more specifically a base class pointer, pointing to a derived class instance), and that declaration does not have a virtual destructor, then the resulting behaviour is undefined, and the destructor of the derived object does not get invoked.

class ITestInterface
{
  public:
    virtual void DoStuff() = 0;
}

class Test : public ITestInterface
{
  public:
     ~Test(){};

     virtual void DoStuff() {};
}

...

ITestInferface *pThing = new Test();
delete *pThing; // undefined

Typically you either define a virtual destructor for the base class, or declare it private to prevent calling delete on an interface pointer.

If you declare the interface with no vtable

class __declspec(novtable) ITestInterface
{
  public:
    virtual void DoStuff() = 0;
}

would deleting an object via the interface pointer now be well defined behaviour, and invoke the appropriate destructor? I don't see why it would, but have been told otherwise.


Solution

  • The effect of __declspec(novtable) is to omit initialization of the vtable pointer in the constructor and destructor of a class. Since the vtable for a pure virtual interface is mostly useless anyway, this is a code-size-reduction technique. It only affects the availability of virtual functions within constructors, so everything is fine as long as you don't make calls requiring virtual dispatch within the constructor (which is a bad idea anyway).

    However, nothing about this attribute says that it magically makes a call to the base type destructor virtual when it wasn't declared so. Based on the documentation alone, deleting an object through a pointer to the interface would still be undefined behavior without an explicitly-declared (or inherited) virtual destructor.