Поведение при удалении базового класса novtable без виртуального деструктора - PullRequest
0 голосов
/ 06 августа 2020

Насколько я понимаю, если вы вызываете delete для указателя интерфейса (или, точнее, указателя базового класса, указывающего на экземпляр производного класса), и это объявление не имеет виртуального деструктора, то результирующее поведение не определено, и деструктор производного объекта не вызывается.

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

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

     virtual void DoStuff() {};
}

...

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

Обычно вы либо определяете виртуальный деструктор для базового класса, либо объявляете его закрытым, чтобы предотвратить вызов delete для указателя интерфейса.

Если вы объявляете интерфейс без vtable

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

, будет ли удаление объекта через указатель интерфейса теперь хорошо определенным поведением и вызовет соответствующий деструктор? Я не понимаю, почему это так, но мне сказали иначе.

1 Ответ

2 голосов
/ 06 августа 2020

Эффект __declspec(novtable) заключается в том, чтобы опустить инициализацию указателя vtable в конструкторе и деструкторе класса. Поскольку vtable для чистого виртуального интерфейса в любом случае по большей части бесполезен, это метод уменьшения размера кода. Это влияет только на доступность виртуальных функций в конструкторах, поэтому все в порядке, пока вы не выполняете вызовы, требующие виртуальной диспетчеризации внутри конструктора (что в любом случае является плохой идеей ).

Однако ничто в этом атрибуте не говорит о том, что он волшебным образом вызывает виртуальный деструктор базового типа, когда он не был объявлен так. Основываясь только на документации, удаление объекта с помощью указателя на интерфейс все равно будет неопределенным поведением без явно объявленного (или унаследованного) виртуального деструктора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...