【发布时间】:2012-08-21 13:38:34
【问题描述】:
我正在尝试在多线程环境中的包装器内创建单例类的实例。我使用包装器来简化我的工作,而不是在 ManagerSources 中多次编写 Lock 和 Unlock。
#define ManagerSOURCES() ManagerSources::GetInstance()
// Singleton
class ManagerSources :public Mutex {
protected:
std::map< std::string , SourcesSPtr > Objects;
static ManagerSources * Instance; // declared in a cpp file
ManagerSources() {}
ManagerSources( const ManagerSources& cpy ) {}
ManagerSources operator=( ManagerSources& cpy) {}
public:
static ManagerSources* GetInstance() {
if ( Instance == NULL )
Instance = new ManagerSources();
return Instance;
}
...
};
// This class is a wrapper for ManagerSources in a thread programming environment
template <class T>
class SingletonThreadSafe {
protected:
T *pointer;
public:
class proxy {
T* pointer;
public:
proxy(T* _pointer) : pointer(_pointer) {
// LOCK();
}
~proxy(){
// UNLOCK();
}
T* operator->() {
return pointer;
}
};
// Default parameter is needed for containers (eg. insert into a map) where we need
// a constructor without parameters
SingletonThreadSafe(T* cpy = NULL ): pointer(cpy) {
}
~SingletonThreadSafe() {
}
SingletonThreadSafe(const SingletonThreadSafe & cpy) {
this->pointer = cpy.pointer;
}
SingletonThreadSafe operator=(SingletonThreadSafe cpy) {
this->pointer = cpy.pointer;
return *this;
}
T operator*() {
return *pointer;
}
proxy operator->() {
return proxy( pointer );
}
};
我有以下声明
typedef SingletonThreadSafe<ManagerSources> aa;
aa( ManagerSources::GetInstance() ); // doesn't work
or
aa( ManagerSOURCES() ); // the same as above; still not working
语法不起作用,它给了我以下错误“函数内不允许定义或重新声明'GetInstance'”。而且,我不知道为什么。 关于如何解决此问题的任何想法?
另外,对我来说奇怪的事实是,如果我用默认参数将构造函数重写为
SingletonThreadSafe(T* cpy = T::GetInstace() ): pointer(cpy) {
}
以下声明有效
aa()->A_Function(A_Parameter);
如果我声明它仍然有效
aa bb( ManagerSOURCES() ); // it works
( SmartPtr<ManagerSources>() = ManagerSOURCES() )->A_Function(A_Parameter); // it works;
// the constructor with the default parameter is called
我不知道为什么我会收到错误“不允许在函数内定义或重新声明 'GetInstance'”。
我正在使用 Xcode 4.4.1 和 LLVM GCC 4.2 编译器。
【问题讨论】:
-
对于初学者,请将您的#define 更改为
#define ManagerSOURCES ManagerSources::GetInstance。然后,将其完全删除;我认为这个宏的伤害大于它的帮助。只创建一个全局函数而不是一个宏要好得多。 -
我认为
assert( "Not recommended!" );这一行应该更频繁地出现方式,即使它永远不会失败。
标签: c++ templates constructor thread-safety singleton