0

有很多人声称他们的单例实现是健壮和通用的,因为它使用元编程结构。

我的目标是对派生类强制执行单例策略,这样我就不必显式(手动)将派生类的构造函数声明为私有。我认为有一种方法可以天真地添加实例静态变量和 getter 作为策略,方法是使模板化单例成为您派生的类的朋友。但这一点都不优雅。

我从这段代码开始,除其他外,它被认为是单例的正确(即完整)设计,而它显然允许多个实例:

template <class CWrappedClass>
class CSingleton
{
protected:
    static CWrappedClass* ms_instance;
private:
    CSingleton(){}
    CSingleton(const CSingleton& ) {}
    CSingleton& operator = (const CSingleton&) {}

public:
    static CWrappedClass& GetInstance()
    {
        if (ms_instance == NULL)
            ms_instance = new CWrappedClass;
        return *ms_instance;
    }
};

template <class CWrappedClass>
CWrappedClass* CSingleton<CWrappedClass>::ms_instance = NULL;

而这个“策略”的单例客户端,使用 CRTP:

class CThing : public CSingleton<CThing>
{
     // friend class CSingleton<CThing>; // only if ctor is private!
public:
    void DoNothing()
    {
        std::cout<<" Nothing \n";
    }
    CThing()
    {
        std::cout<<" single ";
    }
};

注意这不是 CRTP 单例策略的正确实现,它只是问题的一部分!

代码不会按原样编译。基本单例策略类的构造函数声明为私有,因此它不能支持派生实例,除非子对象是此类的朋友。人们通常使构造函数受到保护,这意味着没有什么可以阻止用户使派生类成为非单例的。

问题/问题:是否有任何机制可以强制执行单例策略,而不必手动将派生类的构造函数设为私有?

4

1 回答 1

2

如果您确实希望使用此模式:

  1. 模板的构造函数应该是受保护的,而不是私有的,以便派生类可以访问它。否则它自己的构造函数不能构造基类。

  2. 派生类可以使模板(它是它的基类)成为朋友并拥有一个私有构造函数。

或者,有一个您实现的宏,它实际上在其编译单元中从派生类构造实例。当我确实使用了类似的模型(通过强制修复使用单例的代码并且我无法更改它,只有实际单例的实现方式)时,我选择了这个选项,它实际上通过了boost::once.cpp 中的构造文件。

于 2012-11-12T16:25:38.137 回答