частный деструктор для синглтон-класса - PullRequest
8 голосов
/ 01 апреля 2010

Обязательно ли иметь частный деструктор для одноэлементного класса.

Ответы [ 6 ]

13 голосов
/ 01 апреля 2010

Если синглтон реализован как переменная в глобальной области видимости, он должен иметь деструктор public . Только общедоступные участники доступны в глобальном масштабе.

Если он объявлен как статический член или статический локальный в своем собственном классе, то деструктор может быть закрытым. Деструктор вызывается из области видимости класса, где он доступен при выходе из программы. Это один из способов обеспечения того, чтобы объект был одиночным. Вам нужно строго соблюдать это? Если да, то да. Это зависит от того, что вы подразумеваете под «обязательным».

class A{
private:
    ~A() {}
public:
    static A &getGlobalA() {
        static A a2; // <- or here - better technique
        return a2;   // this is initialized upon 1st access
    };               // and destroyed on program exit

    static A a; // <- constructor, destructor accessed from here
};

A A::a; // <- but "called" from here in terms of control flow
6 голосов
/ 01 апреля 2010

Это может быть не то, что вы ищете .. Но для справки, я использую это следующим образом:

// .h
class Foo {
public:
    static Foo* getInstance();
    static void destroy();
private:
    Foo();
    ~Foo();

    static Foo* myInstance;
};

// .cpp
Foo* Foo::myInstance = NULL;

Foo* Foo::getInstance(){
    if (!myInstance){
        myInstance = new Foo();
    }
    return myInstance;
}
void Foo::destroy(){
    delete myInstance;
    myInstance = NULL;
}

Затем в конце моей программы я вызываю уничтожение объекта. Как указывает Петер, система восстановит память, когда ваша программа закончится, поэтому нет никакой реальной причины. Причина, по которой я использую уничтожение, заключается в том, что Огр жаловался, что я не освободил всю выделенную память. После этого я просто использую это как «хорошую манеру», так как мне нравится убирать за собой.

4 голосов
/ 19 сентября 2016

На мой взгляд, деструктор указателя должен быть приватным. В противном случае кто-то может вызвать «удалить» для вашего экземпляра синглтона. Я знаю, обычно никто этого не сделает. Но если говорить о превосходном дизайне, он должен быть устойчивым ко всем возможным намеренным или единичным повреждениям.

В современном C ++ разрешено объявлять даже частные деструкторы для статически построенных объектов. Вот мой фрагмент кода для Singleton:

class Singleton
{
public:
    static Singleton& GetInstance();

    // Before C++ 11 
private:
    Singleton()  {}
    ~Singleton() {}

    Singleton(const Singleton&);            // Without implementation
    Singleton& operator=(const Singleton&); // Without implementation

    // Since C++ 11
private:
    Singleton()  = default;
    ~Singleton() = default;

public:
    Singleton(const Singleton&)            = delete;
    Singleton& operator=(const Singleton&) = delete;
};

Singleton& Singleton::GetInstance()
{
    static Singleton instance;
    return instance;
}
4 голосов
/ 01 апреля 2010

У всех классов есть деструктор. Если вы не создадите его, компилятор сделает это за вас. Таким образом, ваш вопрос можно перефразировать следующим образом: должен ли деструктор для одноэлементного класса быть закрытым?

Простой ответ - нет, не обязательно.

Более интересный вопрос: хорошая ли идея сделать деструктор синглтон-класса закрытым?

Да, в общем, это хорошая идея. Если вы сделаете его приватным, ваш клиентский код не будет вызывать деструктор случайно. Вызов деструктора вызовет сбой синглтона для всех клиентов, так как экземпляр станет недействительным.

2 голосов
/ 01 апреля 2010

Нет, и вообще объектам в C ++ не предоставляются частные деструкторы. Имейте в виду, что синглтон означает, что существует только один экземпляр, и поэтому необходимо контролировать / предотвращать строительство, а не разрушение. Обычно синглтон имеет закрытый конструктор, открытый деструктор, приватную статическую переменную экземпляра и общедоступную статическую функцию конструирования синглтона get / lazy, хотя в этом шаблоне есть варианты.

1 голос
/ 01 апреля 2010

Вы можете вернуть ссылку на ваш экземпляр синглтона.

class Factory : public IFactory
    {
    private:
        /**
        * This class should not be instantiated through its constructor. Since, it implements 
        * Singleton pattern.
        */
        Factory();      
    public:
        virtual ~Factory();
        /**
        * Accessor method for singleton instance.
        * \note use this static method to access to operations of this class.
        */
        static IFactory& instance(){
            if(!m_instance.get()){
                m_instance.reset(new Factory());    
            }
            return static_cast<IFactory&>(*m_instance);
        }
        /**
        * \see IFactory::create
        */
        virtual boost::shared_ptr<IConnector> create();
    private:
        /* Singleton instance */
        static boost::scoped_ptr<Factory> m_instance;

    };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...