Нужен ли виртуальный деструктор для вашего интерфейса, если вы всегда храните его в shared_ptr? - PullRequest
12 голосов
/ 09 июля 2011

Поскольку boost::/std::shared_ptr обладает преимуществом стирания типа своего удалителя, вы можете делать такие приятные вещи, как

#include <memory>

typedef std::shared_ptr<void> gc_ptr;

int main(){
  gc_ptr p1 = new int(42);
  gc_ptr p2 = new float(3.14159);
  gc_ptr p3 = new char('o');
}

И это правильно удалит все указатели благодаря правильному сохраненному удалителю.

Если вы гарантируете, что каждая реализация вашего интерфейса всегда создается с shared_ptr<Interface> (или make_shared<Interface>), вам действительно нужен деструктор virtual?В любом случае я бы объявил это virtual, но я просто хочу знать, поскольку shared_ptr всегда удаляет тип, с которым он был инициализирован (если не указан другой пользовательский удалитель).

1 Ответ

13 голосов
/ 09 июля 2011

Я бы все равно следовал общему правилу для классов, которые должны быть получены:

Предоставить либо общедоступный виртуальный деструктор, либо защищенный не виртуальный деструктор

Причина в том, что вы не можете контролировать все виды использования, и это простое правило означает, что компилятор установит флаг, если вы попытаетесь delete пройти неправильный уровень в иерархии.Учтите, что shared_ptr не гарантирует, что он вызовет соответствующий деструктор, только то, что он вызовет деструктор статического типа, который использовался в качестве аргумента:

base* foo();
shared_ptr<base> p( foo() );

Если base имеет открытый не-virtual destructor и foo возвращает тип, производный от base, тогда shared_ptr не сможет вызвать правильный деструктор.Если деструктор base является виртуальным, все будет хорошо, если он защищен, компилятор сообщит вам, что там есть ошибка.

...