0

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.

Kindread
  • 926
  • 4
  • 12

1 Answers1

2

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.

cdhowie
  • 158,093
  • 24
  • 286
  • 300
  • Simply declaring it novtable wouldn't 'solve the issue' of not being able to dispatch to the derived class's destructor on deletion though, would it? If there is no virtual destructor for the interface, deleting via the interface pointer won't look up the derived class's destructor. – Kindread Aug 06 '20 at 01:13
  • 1
    @Kindread I apparently didn't process that part of the question correctly. Let me edit. – cdhowie Aug 06 '20 at 01:15
  • Thanks! Should I clarify my question in some way, to make the part you had trouble with clearer to future readers? – Kindread Aug 06 '20 at 01:21
  • @Kindread No, your question is totally fine. I was distracted while reading the question and didn't catch the important detail of a non-virtual destructor, focusing instead on the novtable part. – cdhowie Aug 06 '20 at 01:22