template<typename T>
class Singleton{
public:
static T& getInstance(){
static T instance;
return instance;
}
virtual ~Singleton(){
std::cout<<"destructor called!"<<std::endl;
}
Singleton(const Singleton&)=delete;
Singleton& operator =(const Singleton&)=delete;
protected:
Singleton(){
std::cout<<"constructor called!"<<std::endl;
}
};
/********************************************/
// Example:
// 1.声明一个友元类
// 2.构造函数的访问权限:私有
class DerivedSingle:public Singleton<DerivedSingle>{
// !!!! attention!!!
// needs to be friend in order to
// access the private constructor/destructor
friend class Singleton<DerivedSingle>;//友元类
public:
DerivedSingle(const DerivedSingle&)=delete;
DerivedSingle& operator =(const DerivedSingle&)= delete;
private:
DerivedSingle()=default;
};
int main(int argc, char* argv[]){
DerivedSingle& instance1 = DerivedSingle::get_instance();
DerivedSingle& instance2 = DerivedSingle::get_instance();
return 0;
}
以上实现一个单例的模板基类,使用方法如例子所示意,子类需要将自己作为模板参数T 传递给 Singleton<T>
模板; 同时需要将基类声明为友元,这样才能调用子类的私有构造函数。
基类模板的实现要点是:
- 构造函数需要是 protected,这样子类才能继承;
- 使用了奇异递归模板模式CRTP(Curiously recurring template pattern);
- getInstance方法通过返回单例引用,才能获得对象;
- 在这里基类的析构函数可以不需要 virtual ,因为子类在应用中只会用 Derived 类型,保证了析构时和构造时的类型一致。