Да, таким способом можно реализовать shared_ptr.Boost делает, и стандарт C ++ 11 также требует такого поведения.В качестве дополнительной гибкости shared_ptr управляет не только счетчиком ссылок.Так называемое средство удаления обычно помещается в тот же блок памяти, который также содержит счетчики ссылок.Но самое интересное в том, что тип этого удалителя не является частью типа shared_ptr.Это называется «стиранием типа» и в основном является тем же методом, который используется для реализации «полиморфных функций» boost :: function или std :: function для сокрытия фактического типа функтора.Чтобы ваш пример работал, нам нужен шаблонный конструктор:
template<class T>
class shared_ptr
{
public:
...
template<class Y>
explicit shared_ptr(Y* p);
...
};
Итак, если вы используете это с вашими классами Base и Derived ...
class Base {};
class Derived : public Base {};
int main() {
shared_ptr<Base> sp (new Derived);
}
... шаблонныйконструктор с Y = Derived используется для создания объекта shared_ptr.Таким образом, конструктор имеет возможность создать соответствующий объект удаления и счетчики ссылок и сохраняет указатель на этот блок управления в качестве элемента данных.Если счетчик ссылок достигает нуля, для удаления объекта будет использоваться ранее созданное и осведомленное о Derived средство удаления.
Стандарт C ++ 11 может сказать следующее об этом конструкторе (20.7.2.2.1):
Требуется: p
должно быть конвертировано в T*
.Y
должен быть полным типом. Выражение delete p
должно быть правильно сформировано, должно иметь четко определенное поведение и не создавать исключений.
Эффекты: Создает shared_ptr
объект что владеет указателем p
.
…
и для деструктора (20.7.2.2.2):
Эффекты: Если *this
равен пуст или делится правами собственности с другим экземпляром shared_ptr
(use_count() > 1
), побочные эффекты отсутствуют.В противном случае, если *this
принадлежит объект p
и вызывается удалитель d
, d(p)
вызывается. В противном случае, если *this
имеет указатель p
и вызывается delete p
.
(выделение жирным шрифтом - мое).