以下代码是我对Singleton Pattern的实现。
#include <iostream>
template<class T>
class Uncopyable
{
protected:
Uncopyable(){}
~Uncopyable(){}
private:
Uncopyable(const Uncopyable<T>&);
Uncopyable& operator=(const Uncopyable<T>&);
};
template <class T>
class Singleton : private Uncopyable<T>
{
public:
static T* getInstancePtr()
{
return instance;
}
protected:
Singleton<T>()
{
if(instance == 0)
{
instance = new T();
}
};
~Singleton<T>()
{
};
private:
static T* instance;
};
template<class T> T* Singleton<T>::instance = 0;
class Test : public Singleton<Test>
{
public:
Test(){};
~Test(){};
inline void test() const
{
std::cout << "Blah" << std::endl;
}
private:
friend class Singleton<Test>;
protected:
};
int main(int argc, char* argv[])
{
Test* t = Test::getInstancePtr();
Test* t2 = Test::getInstancePtr();
t->test();
t2->test();
return 0;
}
它以这种形式工作,但我不确定它是否真的是正确的,因为Singleton的构造函数和析构函数受到保护而不是私有。如果我将它们声明为私有,则代码将无法编译,因为类无法访问它们。这个实现是否可以安全使用,或者我可以做些什么来改进它以确保只创建和使用一个实例。
由于
答案 0 :(得分:7)
这肯定是单身人士的错误实施。该实现存在太多问题。
在C ++ 11中,您可以使用std::call_once
和std::once_flag
来实现单例模式。这是一个例子:
//CRTP base singleton class
template<typename TDerived>
class Singleton
{
static std::unique_ptr<TDerived> m_instance;
static std::once_flag m_once;
protected:
Singleton() {}
public:
~Singleton() { }
static TDerived & GetInstance()
{
std::call_once
(
Singleton::m_once,
[] (){ Singleton::m_instance.reset( new TDerived() ); }
);
return *m_instance;
}
};
template<typename TDerived>
std::unique_ptr<TDerived> Singleton<TDerived>::m_instance;
template<typename TDerived>
std::once_flag Singleton<TDerived>::m_once;
现在你可以从中得到:
class Demo : public Singleton<Demo>
{
public:
void HelloWorld() { std::cout << "HelloWorld" << std::endl; }
};
//call HelloWorld() function through singleton instance!
DemoSingleton::GetInstance().HelloWorld();
答案 1 :(得分:2)
您发布的代码存在一些问题。
Uncopyable
类不需要模板化Singleton
类不是线程安全的Singleton
实例永远不会被删除我会重新实现你的访问者:
static T& GetInstance()
{
static T instance;
return instance;
}
然后确保在应用程序的主线程中调用Singleton<T>::GetInstance()
(在初始化期间)以避免任何线程问题。
答案 2 :(得分:1)
答案 3 :(得分:1)
不,这不是单例模式的好实现,它不起作用! 示例中唯一的Test实例是NULL!永远不会调用构造函数!
您需要将Singleton :: getInstancePtr更改为:
public:
static T* getInstancePtr()
{
if(instance == 0)
{
instance = new T();
}
return instance;
}
protected:
Singleton<T>() {};
现在将调用Test的构造函数。
答案 4 :(得分:0)
通常单例对象在程序的生命周期中存在,所以我没有像那样实现它们,因为你使用动态分配,然后有人必须释放它并返回指向你的单例对象的指针,然后你可能会意外删除它,所以我会用这样的东西:
template< class T >
struct Singleton : Uncopyable<T> {
public:
static T& get_instance() {
static T res;
use( res ); // make sure object initialized before used
return res;
}
private:
static void use( T& ) {}
};
答案 5 :(得分:0)
在C ++中没有正确实现Singleton反模式。
此尝试的主要问题是:
Singleton
才能创建实例。您的示例永远不会创建实例,t->test()
错误地通过空指针调用函数。Singleton
。错误较少的实现可能更像是这样:
template <typename T>
T & singleton()
{
static T instance;
return instance;
}
但是这仍然存在问题:特别是,实例可能会在其他静态对象之前被销毁,这些静态对象可能会尝试在其析构函数中访问它。