Какая польза от деструктора как частного?Какая польза от деструктора как частного?
ответ
В принципе, в любое время, когда какой-либо другой класс должен отвечать за жизненный цикл объектов вашего класса или у вас есть причина предотвратить разрушение объекта, вы можете сделать деструктор закрытым.
Например, если вы делаете какую-либо ссылку на подсчет, вы можете иметь объект (или менеджер, который был «другом»), ответственный за подсчет количества ссылок на себя и удаление его, когда число достигает нуля. Частный dtor не позволил бы кому-либо еще удалять его, когда еще были ссылки на него.
Для другого примера, если у вас есть объект, у которого есть менеджер (или сам), который может его уничтожить или может отказаться уничтожить его в зависимости от других условий в программе, таких как открытое соединение с базой данных или файл написано. У вас может быть метод «request_delete» в классе или менеджере, который будет проверять это условие, и он будет либо удалять, либо отклонять, и возвращать статус, сообщающий вам, что он сделал. Это гораздо более гибкий, чем просто вызов «delete».
Если вы не хотите, чтобы пользователи обращались к деструктору, т. Е. Вы хотите, чтобы объект был уничтожен только с помощью других средств.
http://blogs.msdn.com/larryosterman/archive/2005/07/01/434684.aspx дает пример, где объект подсчитывается и должен быть уничтожен только самим объектом, когда счетчик обращается в нуль.
Класс может быть удален только сам по себе. Полезно, если вы создаете какую-то попытку подсчета засчитанного объекта. Тогда только метод release может удалить объект, возможно, помогая избежать ошибок.
Такой объект никогда не может быть создан в стеке. Всегда в куче. И удаление должно быть сделано через друга или участника. Продукт может использовать единую иерархию объектов и пользовательский менеджер памяти - в таких сценариях может использоваться частный 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;
}
Удаление должно быть выполнено через друга/или участника/ – MSalters
Это уже было сказано - поэтому я пропустил его. Будет ли updata (во втором чтении мое утверждение выглядит слишком сильным). – dirkgently
Исправление: такой объект * может * быть создан в стеке (но только в области действия друга или самого себя). –
Я знаю, что вы спрашивали о частном деструкторе. Вот как я использую защищенные. Идея заключается в том, что вы не хотите удалять основной класс с помощью указателя на класс, который добавляет дополнительные функции к основному.
В приведенном ниже примере я не хочу, чтобы 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(){}
};
COM использует эту стратегию для удаления экземпляра. COM делает деструктор закрытым и предоставляет интерфейс для удаления экземпляра.
Вот пример того, как будет выглядеть метод Release.
int MyRefCountedObject::Release()
{
_refCount--;
if (0 == _refCount)
{
delete this;
return 0;
}
return _refCount;
}
Объекты ATL COM являются ярким примером этого шаблона.
Инструктивный. Благодаря! –
dirkgly неправильный. Вот пример объекта с частным c-tor и d-tor, созданным в стеке (здесь я использую статическую функцию-член, но это можно сделать с помощью функции-друга или класса друга).
#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
Я уверен, что dirkgently означает, что код, который * использует * ваш класс, не может создать экземпляр класса в стеке. Конечно, вы все равно можете создать класс класса * в методах * класса, поскольку в этом контексте вы можете получить доступ к закрытым членам. –
Добавление к ответам уже присутствующих здесь; частные конструкторы и деструкторы весьма полезны при реализации factory, где создаваемые объекты должны быть выделены в куче. Объекты, в общем, будут созданы/удалены статическим членом или другом. Пример типичного использования:
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
}
см СНИМИТЕ # 4 http://www.gotw.ca/publications/mill18.htm – Eric
Этот aswer отсутствует некоторый пример кода. – mrgloom