Поскольку 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 · рейтинг 14 · David Rodríguez - dribeas
Я бы по-прежнему следовал общему правилу для классов, которые должны быть производными:
Предоставьте публичный виртуальный деструктор или защищенный невиртуальный деструктор.
Причина в том, что вы не можете контролировать все виды использования, и это простое правило означает, что компилятор будет отмечать, если вы попытаетесь delete пройти неправильный уровень в иерархии. Учтите, что shared_ptr не гарантирует, что он вызовет соответствующий деструктор, только то, что он вызовет деструктор статического типа, который использовался в качестве аргумента:
base* foo();
shared_ptr<base> p( foo() );
Если base имеет общедоступный не виртуальный деструктор и foo возвращает тип, производный от base, то shared_ptr не сможет вызвать правильный деструктор. Если деструктор base виртуальный, все будет хорошо, если он защищен, компилятор сообщит вам, что там ошибка.