是否必须为单例类设置私有析构函数。
答案 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;
}