Я клиент класса A, деструктор которого определен как protected. Вдобавок я не могу изменить его интерфейс (я сознательно написал «сторонний класс», хотя имел в виду, что по какой-либо причине вам не разрешено изменять его интерфейс. Итак, как я могу использовать boost :: shared_ptr в таком случае ? Деструктор виртуальный:
Class Foo {
public:
void Destroy () {}
protected:
virtual ~Foo () {}
}
Для Foo он предоставляет метод "Destroy".
Прямое использование Следующий код не компилируется:
boost::shared_ptr <Foo> a = boost::make_shared <Foo> ();
Сообщение компилятора: ... ошибка ... "Foo :: ~ Foo () недоступен ...
Также компилятор на моем рабочем месте не поддерживает c ++ 11.
2 ответа
Вы можете создать промежуточный класс в качестве вспомогательной полиморфной базы:
Пример с использованием только c ++ 03 Live On Coliru :
#include <boost/shared_ptr.hpp>
#include <iostream>
class Foo { // "abstract"
public:
virtual void Destroy () { std::cout << __FUNCTION__ << "\n"; }
protected:
virtual ~Foo () {}
};
class FooBase : public Foo {
public:
static void Deleter(FooBase* p) {
if (p)
p->Destroy();
delete p;
}
// protected:
virtual ~FooBase() { std::cout << __FUNCTION__ << "\n"; }
};
class FooDerived : public FooBase
{
~FooDerived() { std::cout << __FUNCTION__ << "\n"; }
};
int main()
{
boost::shared_ptr<FooBase> p(new FooDerived, FooBase::Deleter);
}
Печать:
Destroy
~FooDerived
~FooBase
Примечание . Каким может быть деструктор на самом деле protected
сейчас. Это гарантирует, что все разрушения пройдут через FooBase::Deleter
FooDerived
выводит Foo
непосредственно в случае OP. Если нет, то это такое хорошее решение!
boost::bind
больше не используется. Обратите внимание, что деструктор теперь может быть красивым и приватным, если хотите (/cc @ikh)
FooDerived
— пример класса, производного от Foo
. но решение можно использовать, если все классы, производные Foo
, могут быть изменены.
FooBase
имеет единственную цель - служить сервером в качестве "удаляемого" посредника.
Просто.
boost::shared_ptr<Foo> ptr(new Foo(), [](Foo *p){ p->Destroy(); });
Заключение ответов: Это проблема неправильного дизайна библиотеки (деструктор абстрактного класса должен быть public
..). Таким образом, вы не можете использовать shared_ptr
с этой библиотекой, или вам следует изменить деструктор на public
, чтобы использовать shared_ptr
, отредактировав файл заголовка библиотеки, даже если он такой плохой < / сильный>.
delete
на p
?
delete nullptr;
в порядке. Без проблем
delete
, с умными указателями или без них. Вероятно, он не предназначен для удаления вручную.
Похожие вопросы
Новые вопросы
c++
C++ — это язык программирования общего назначения. Изначально он разрабатывался как расширение C и имел аналогичный синтаксис, но теперь это совершенно другой язык. Используйте этот тег для вопросов о коде, который будет скомпилирован с помощью компилятора C++. Используйте тег версии для вопросов, связанных с конкретной стандартной версией [C++11], [C++14], [C++17], [C++20] или [C++23]. и т.д.