单例类的私有析构函数

时间:2010-04-01 10:40:45

标签: c++ singleton

是否必须为单例类设置私有析构函数。

7 个答案:

答案 0 :(得分:13)

如果单例在全局范围内实现为变量,则它必须具有 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

答案 1 :(得分:6)

这可能不是你想要的......但作为参考,我使用它如下:

// .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;
}

然后在我的程序结束时,我在对象上调用destroy。正如Péter所指出的那样,当你的程序结束时系统会回收内存,所以没有真正的理由。我使用销毁的原因是Ogre抱怨我没有释放我分配的所有内存。在那之后我只是用它作为“好的方式”,因为我喜欢自己清理。

答案 2 :(得分:4)

所有类都有析构函数。如果您没有创建一个,编译器将为您执行此操作。所以你的问题可以改写为:单例类的析构函数是否必须私有?

简单的答案是否定的,不一定是。

一个更有趣的问题:将单例类的析构函数设为私有是一个好主意吗?

是的,总的来说,这是一个好主意。如果您将其设为私有,那么您的客户端代码将不会意外调用析构函数。调用析构函数会导致所有客户端的单例失败,因为实例将变为无效。

答案 3 :(得分:4)

在我看来,签名的析构函数应该是私有的。否则,有些人可以打电话来删除&#39;为你的单身实例。我知道,通常没有人会这样做。但是,如果我们谈论卓越设计,它必须能够抵抗所有可能的或单位的损害。

使用现代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 :(得分:2)

不,并且通常在C ++中的对象没有给出私有析构函数。请记住,Singleton意味着只有一个实例,因此需要控制/防止构造,而不是破坏。通常,单例具有私有构造函数,公共析构函数,私有静态实例变量和公共静态单例get / lazy构造函数,尽管该模式存在变体。

答案 5 :(得分:1)

您可以返回对您的单例实例的引用。

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;

    };

答案 6 :(得分:0)

从程序员的角度来看,并不需要将私有析构函数作为单例的一部分,而从设计的角度来看,则是必不可少的。

这可以避免滥用课程。

但是,如果添加一个私有析构函数,则必须实例化您的类:

  • 在函数/方法中:因为如果将其创建为全局变量,则会失去使用单例(为避免全局变量而创建)的兴趣。
  • 使用正确的实例化方法:如果析构函数是私有的,则如果将其实例化为“经典”局部变量,则无法在程序末尾删除您的类,因为无法访问它。因此,您必须像这样实例化它:
Singleton * potatoe = &Singleton::getInstance();

在这里,我们创建一个名为“ potatoe”的弱指针,该指针与“ getInstance”函数的结果地址相对应。 结果是析构函数将不会在函数末尾被调用。 但是,因为(在“ getInstance”中)在“静态”方法中将变量声明为“静态”,所以析构函数将在程序结束时被调用,而无需您必须这样做。

这是我的代码。随时发表评论。

// "class.hpp" file
class Singleton {
public:
    static Singleton& getInstance() {
        static Singleton S;
        return S;
    } 
private:
    Singleton();
    ~Singleton();
};

// "main.cpp" file
#include "class.hpp"

int main()
{
        Singleton * patatoe = &Singleton::getInstance();
        Singleton * tomatoe = &Singleton::getInstance();
        Singleton * salad = &Singleton::getInstance();
        return 0;
}