Какая польза от деструктора как частного?
-
08-07-2019 - |
Вопрос
Какая польза от деструктора как частного?
Решение
По сути, всякий раз, когда вы хотите, чтобы какой-то другой класс отвечал за жизненный цикл объектов вашего класса, или у вас есть причина предотвратить уничтожение объекта, вы можете сделать деструктор приватным.
Например, если вы выполняете какие-то действия по подсчету ссылок, у вас может быть объект (или менеджер, который был «другом»), ответственный за подсчет количества ссылок на себя и удаление его, когда число хиты ноль. Закрытый dtor не позволит кому-либо удалить его, если на него еще есть ссылки.
В другом случае, что если у вас есть объект, у которого есть менеджер (или он сам), который может уничтожить его или может отказаться от его уничтожения в зависимости от других условий в программе, таких как открытое соединение с базой данных или файл написано. Вы могли бы иметь " request_delete " метод в классе или менеджер, который проверит это условие и удалит или отклонит его, и вернет статус, сообщающий вам, что он сделал. Это гораздо более гибко, чем просто вызывать " удалить ".
Другие советы
Такой объект никогда не может быть создан в стеке. Всегда в куче. И удаление должно быть сделано через друга или члена. Продукт может использовать одну иерархию объектов и пользовательский диспетчер памяти - в таких сценариях может использоваться личный dtor.
#include <iostream>
class a {
~a() {}
friend void delete_a(a* p);
};
void delete_a(a* p) {
delete p;
}
int main()
{
a *p = new a;
delete_a(p);
return 0;
}
Если вы не хотите, чтобы пользователи обращались к деструктору, т.е. вы хотите, чтобы объект был уничтожен только другими способами.
http://blogs.msdn.com/larryosterman/ В архиве / 2005/07/01 / 434684.aspx приведен пример, в котором объект имеет счетную ссылку и должен уничтожаться только самим объектом, когда счетчик становится равным нулю.
COM использует эту стратегию для удаления экземпляра. COM делает деструктор приватным и предоставляет интерфейс для удаления экземпляра.
Вот пример того, как должен выглядеть метод Release.
int MyRefCountedObject::Release()
{
_refCount--;
if ( 0 == _refCount )
{
delete this;
return 0;
}
return _refCount;
}
COM-объекты ATL являются ярким примером этого шаблона. Р>
Добавление к ответам, уже присутствующим здесь; частные конструкторы и деструкторы весьма полезны при реализации фабрики , где создается объекты должны быть размещены в куче. Объекты, как правило, создаются / удаляются статическим членом или другом. Пример типичного использования:
class myclass
{
public:
static myclass* create(/* args */) // Factory
{
return new myclass(/* args */);
}
static void destroy(myclass* ptr)
{
delete ptr;
}
private:
myclass(/* args */) { ... } // Private CTOR and DTOR
~myclass() { ... } //
}
int main ()
{
myclass m; // error: ctor and dtor are private
myclass* mp = new myclass (..); // error: private ctor
myclass* mp = myclass::create(..); // OK
delete mp; // error: private dtor
myclass::destroy(mp); // OK
}
Класс может быть удален только сам по себе. Полезно, если вы создаете некоторый объект подсчета ссылок. Тогда только метод release может удалить объект, что поможет вам избежать ошибок.
Я знаю, что вы спрашивали о частном деструкторе. Вот как я использую защищенные. Идея состоит в том, что вы не хотите удалять основной класс через указатель на класс, который добавляет дополнительные функции к основному.
В приведенном ниже примере я не хочу, чтобы GuiWindow удалялось через указатель HandlerHolder. Р>
class Handler
{
public:
virtual void onClose() = 0;
protected:
virtual ~Handler();
};
class HandlerHolder
{
public:
void setHandler( Handler* );
Handler* getHandler() const;
protected:
~HandlerHolder(){}
private:
Handler* handler_;
};
class GuiWindow : public HandlerHolder
{
public:
void finish()
{
getHandler()->onClose();
}
virtual ~GuiWindow(){}
};
прямо не так. Вот пример объекта с частным c-tor и d-tor, созданным в стеке (здесь я использую статическую функцию-член, но это также можно сделать с помощью функции Friend или класса Friend).
#include <iostream>
class PrivateCD
{
private:
PrivateCD(int i) : _i(i) {};
~PrivateCD(){};
int _i;
public:
static void TryMe(int i)
{
PrivateCD p(i);
cout << "inside PrivateCD::TryMe, p._i = " << p._i << endl;
};
};
int main()
{
PrivateCD::TryMe(8);
};
Этот код будет выводить: внутри PrivateCD :: TryMe, p._i = 8
Это может быть способ решения проблемы в Windows, где каждый модуль может использовать различную кучу, например куча отладки . Если эта проблема не решена правильно bad < a href = "https://stackoverflow.com/questions/443147/c-mix-new-delete-between-libs"> вещи могут произойти.