用于继承树的可继承单例模板类
最近需要在一个继承树中大量用到单例模式,最经典的单例实现是不够用了。
经典单例实现
class Singleton { public: ~Singleton() = default; Singleton(const Singleton &) = delete; Singleton &operator=(const Singleton &) = delete; Singleton(Singleton &&) = delete; Singleton &operator=(Singleton &&) = delete; /// Get singleton static Singleton &Instance() { static Singleton instance_; return instance_; } private: Singleton() = default; };
就算把构造函数改成protected的允许继承,但static的Instance()函数在每个子类中都得重写。这还只是饿汉模式的情况,如果是懒汉模式,还要定义私有变量储存单例实例,并且要在构造函数中加锁避免多线程问题,重写的代码太多了,实在是bug藏身的好地方。
在这种情况下当然首先会想到模板继承的解决方法:
template <typename T>
class Singleton {
public:
virtual ~Singleton() = default;
Singleton(const Singleton &) = delete;
Singleton &operator=(const Singleton &) = delete;
Singleton(Singleton &&) = delete;
Singleton &operator=(Singleton &&) = delete;
/// Get singleton
static T &Instance() {
static T instance_;
return instance_;
}
protected:
Singleton() = default;
};
模板就是自然的根据不同的类型来自动生成代码的好工具,这个模板类就可以简单地被继承来获得单例模式了。关键有一点,就是要把这个模板类声明为友元类,因为它要调用你隐藏起来的构造函数。
class Object : public Singleton<Object> {
public:
~Object() override = default;
Object(const Object &) = delete;
Object &operator=(const Object &) = delete;
Object(Object &&) = delete;
Object &operator=(Object &&) = delete;
private:
Object() = default;
friend Singleton<Object>;
};
但这个模板在我的继承树里面依然有问题,因为
class BaseClass : public Singleton<BaseClass>{...};
class DerivedClass : public BaseClass, public Singleton<DerivedClass>{...};
里面虽然父类和子类都实现了单例模式,但由于子类是多继承的关系,会存在static的Instance()函数二义性问题,把模板的继承改成private的也无法解决。
不会又要全部重写一遍Instance()函数的实现来覆盖掉继承下来的Instance()吧?!
当然不!C++的using语句最终帮我解决了这个问题。只要在每个类中声明一下
using Singleton<T>::Instance;
就可以解决这个二义性问题。
然后我的实际需要是Instance()返回基类的引用,因此我最后实现的模板是这样的:
/**
* @brief Singleton template for easily deriving from an inheritance tree.
* @tparam T Class derived from U Class.
*
* Guidelines for derived classes:
* ** privately derived from Singleton<T, U>
* ** hide constructors of T
* ** make class Singleton<T, U> friendly
* ** declare using Singleton<T, U>::Instance()
*/
template <typename T, typename U = T>
class Singleton {
public:
virtual ~Singleton() = default;
Singleton(const Singleton &) = delete;
Singleton &operator=(const Singleton &) = delete;
Singleton(Singleton &&) = delete;
Singleton &operator=(Singleton &&) = delete;
protected:
Singleton() = default;
/// Get singleton
static std::shared_ptr<U> Instance() { return instance_; }
private:
/// Singleton instance
static std::shared_ptr<U> instance_;
};
template <typename T, typename U>
std::shared_ptr<U> Singleton<T, U>::instance_ = std::shared_ptr<U>(new T);
使用方法在注释中说明:
- 继承private Singleton<T, U>
- 把构造函数隐藏起来
- 声明friend Singleton<T, U>
- 在public中声明using Singleton<T, U>::Instance;