Наверное, это что-то очень тривиальное, но я не владею C++.
class hardwareMonitor : public hardwareMonitor_
{
public:
// Перегруженные методы getInstance для отражения оригинальных конструкторов
static std::shared_ptr<hardwareMonitor> getInstance();
void cleanup();
// Удаление конструктора копирования и оператора присваивания
hardwareMonitor(const hardwareMonitor&) = delete;
hardwareMonitor& operator=(const hardwareMonitor&) = delete;
private:
// Приватные конструкторы, отражающие те, что в hardwareMonitor_
hardwareMonitor() : hardwareMonitor_() {}
// Деструктор
~hardwareMonitor() = default;
// Указатель на единственный экземпляр класса
static std::shared_ptr<hardwareMonitor> instance;
};
и реализация метода getInstance()
(для создания экземпляра синглтона) с делетором:
std::shared_ptr<hardwareMonitor> hardwareMonitor::getInstance()
{
if (instance == nullptr)
{
instance = std::make_shared<hardwareMonitor>(new hardwareMonitor(), [](hardwareMonitor * p) { p->cleanup(); });
}
return instance;
}
void hardwareMonitor::cleanup()
{
delete this;
}
Но я получаю ошибку:
\include\xmemory(293,9): ошибка C2248: ‘hardwareMonitor::~hardwareMonitor’: нельзя получить доступ к закрытому члену класса ‘hardwareMonitor’
строка в xmemory
:
_Obj.~_Ty();
Возможно ли использовать shared_ptr
с пользовательским делетором, не раскрывая деструктор?
Ответ
Чтобы использовать std::shared_ptr
с пользовательским делетором, не раскрывая деструктор, нужно сделать некоторые изменения в вашей реализации. Ваша текущая реализация пытается использовать new
для создания экземпляра класса, но std::make_shared
не предназначен для использования с пользовательскими делеторами, так как он не позволяет контролировать, как объект будет уничтожаться.
Но, чтобы все работало корректно, вы можете использовать std::shared_ptr
с кастомным делетором через лямбда-функцию или определение делетора. Вот как это можно сделать:
- Замените вызов
std::make_shared
на созданиеshared_ptr
с использованием явного вызоваnew
с пользовательским делетором. - В качестве делетора просто вызовите
cleanup
.
Ниже приведён исправленный код:
#include <memory>
class hardwareMonitor_ {}; // Предположим, что это базовый класс
class hardwareMonitor : public hardwareMonitor_
{
public:
// Методы для получения экземпляра
static std::shared_ptr<hardwareMonitor> getInstance();
void cleanup();
// Удаляем конструктор копирования и оператор присваивания
hardwareMonitor(const hardwareMonitor&) = delete;
hardwareMonitor& operator=(const hardwareMonitor&) = delete;
private:
// Приватный конструктор
hardwareMonitor() : hardwareMonitor_() {}
// Приватный деструктор
~hardwareMonitor() = default;
// Указатель на единственный экземпляр класса
static std::shared_ptr<hardwareMonitor> instance;
};
// Инициализация статического член-данного
std::shared_ptr<hardwareMonitor> hardwareMonitor::instance = nullptr;
std::shared_ptr<hardwareMonitor> hardwareMonitor::getInstance()
{
if (instance == nullptr)
{
// Создаем shared_ptr с пользовательским делетором
instance.reset(new hardwareMonitor(), [](hardwareMonitor* p) {
p->cleanup(); // Вызываем cleanup
delete p; // Затем удаляем указатель
});
}
return instance;
}
void hardwareMonitor::cleanup()
{
// Здесь можем поместить логику очистки, если понадобится
}
Объяснение изменений:
-
Использование
reset
: Вместо использованияstd::make_shared
, мы используемreset
, чтобы установить новый объектhardwareMonitor
. Это позволяет нам явно указать делетор для управления уничтожением объекта. -
Удаление объекта в делеторе: Внутри делетора мы сначала вызываем метод
cleanup()
, а затем удаляем объект. - Статический указатель: Мы инициализируем
instance
в самом начале, что гарантирует, что он будет иметь значениеnullptr
перед первым обращением.
Таким образом, при вызове getInstance()
создается новый объект hardwareMonitor
, и управление его жизненным циклом будет корректно обрабатываться с помощью std::shared_ptr
, не exposing деструктор класса.