Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;单例模板类继承_C++_Templates_Inheritance_Singleton_Friend - Fatal编程技术网

C++ C++;单例模板类继承

C++ C++;单例模板类继承,c++,templates,inheritance,singleton,friend,C++,Templates,Inheritance,Singleton,Friend,我有一个抽象的单例类。我的目标是,任何子类只需实现init()函数,而无需其他任何功能。以下是我所做的: template <typename T> class Singleton { public: Singleton() { init(); } static T& instance() { static T instance;

我有一个抽象的单例类。我的目标是,任何子类只需实现init()函数,而无需其他任何功能。以下是我所做的:

template <typename T>
class Singleton
{
    public: 

        Singleton()
        {
            init();
        }

        static T& instance()
        {
            static T instance;
            return instance;
        }

    protected:
        virtual void init() = 0;   
};

class SubSingleton : public Singleton<SubSingleton>
{
    protected: 
        void init()
        {
            cout << "Init SubSingleton" << endl;
        }
};
模板
单件阶级
{
公众:
Singleton()
{
init();
}
静态T&实例()
{
静态T实例;
返回实例;
}
受保护的:
虚拟void init()=0;
};
类子个体:公共个体
{
受保护的:
void init()
{

cout您似乎混合了两种类型的脊髓灰质炎:

1) 如果您想“静态地”调用
subingleton::init()
,即使用CRTP,则不需要在基类中定义它,但实际上必须使基类可以访问它

2) 但如果将init()定义为虚拟,则使用动态同构,而不需要将
init()
public:

static T& instance() 
{ 
  static T instance; 
  static_cast<Singleton<T> &>(instance).init(); 
  return instance; 
} 
static T&instance()
{ 
静态T实例;
static_cast(instance.init();
返回实例;
} 

问题在于您没有按照预期使用虚拟函数。也就是说,现在没有多态性。为什么?因为您在直接派生对象上调用了init()。当您调用init()时,使用虚拟的init()函数在基类引用或基类指针上进行调用,如下所示。然后从基类范围进行调用,并且由于instance()方法是基类方法,因此从中调用受保护的方法是完全正确的

    static T& instance()
    {
        static T myInstance;
        Singleton<T>& t = myInstance;  // Just define a dummy reference here.
        t.init();
        return myInstance;
    }
static T&instance()
{
静态myt实例;
Singleton&t=myInstance;//只需在此处定义一个伪引用即可。
t、 init();
返回myInstance;
}
您根本不需要这个init()东西。它只会在这里产生问题

template <typename T>
class Singleton
{
    public: 
        static T& instance()
        {
            static T instance;
            return instance;
        }
};

class SubSingleton : public Singleton<SubSingleton>
{
    public: 
        SubSingleton()
        {
            cout << "Init SubSingleton" << endl;
        }
};
模板
单件阶级
{
公众:
静态T&实例()
{
静态T实例;
返回实例;
}
};
类子个体:公共个体
{
公众:
子辛格尔顿()
{

cout调用
instance()
两次将导致
init()
被调用两次:这正常吗?你的
模板单例是什么;
?它似乎并不要求派生类实际上是单例的,所以让派生类像通常那样在构造函数中执行初始化不是更简单吗?(事实上,即使您希望将所需的派生类设置为单例,我仍然不认为有理由在构造函数之后立即调用“init”函数。)第一:您现在不创建实例,第二:bool-isInit会有所帮助,但您在这里期望的可能是create而不是Init。目前似乎有点混淆。在“edit2”之后:您不应该从基构造函数调用Init(),因为当调用基构造函数时,派生对象(即其成员)还不存在。所以即使调用派生::init()静态地说,你不能做任何有用的事情。+1很好的一点,但是你对函数模板和函数体中的一个变量都使用了名称
instance
。这不会编译。@Walter你能引用标准的段落禁止这样做吗?据我所知,它是允许的。也许它是允许的,但它确实不会编译模糊的names@MareInfinitus,这里没有歧义,它编译得很好(用MSVC10测试)。@Mare:是允许的,用gcc编译
template <typename T>
class Singleton
{
    public: 
        static T& instance()
        {
            static T instance;
            return instance;
        }
};

class SubSingleton : public Singleton<SubSingleton>
{
    public: 
        SubSingleton()
        {
            cout << "Init SubSingleton" << endl;
        }
};