C++ 如何在C++;

C++ 如何在C++;,c++,inheritance,singleton,C++,Inheritance,Singleton,这是我刚刚读到的 他用C++实现Singleton的方法使我感到困惑。我有几个问题,这是他的密码: template<typename T> class Singleton { public: static T& getInstance() { //Question 1 return instance; } private: static T instance; }; class DebugLog : public Singleto

这是我刚刚读到的

他用C++实现Singleton的方法使我感到困惑。我有几个问题,这是他的密码:

template<typename T>
class Singleton {
public:
    static T& getInstance() {  //Question 1
        return instance;
    }
private:
    static T instance;
};

class DebugLog : public Singleton<DebugLog> {  //Question 2
public:
    void doNothing() {}
};
模板
单件阶级{
公众:
静态T&getInstance(){//问题1
返回实例;
}
私人:
静态T实例;
};
类DebugLog:publicsingleton{//问题2
公众:
void doNothing(){}
};
问题

  • 我认为我们应该将
    静态T&getInstance()
    的定义放在类主体之外,对吗

  • 他试图使
    classdebuglog
    成为一个单例类,但当他继承
    singleton
    时,
    DebugLog
    并不存在,对吗?如果正确,那么模板类
    Singleton
    如何实例化一个不存在的类

  • 1) 不,不管你如何构造你的代码<顺便说一下,code>Singleton不是一个类:它是一个模板。由于完整的模板定义无论如何都必须在任何实例化站点上都是可访问的,因此您最好以内联方式定义所有内容

    2)
    class-DebugLog:public-Singleton
    可以。我们不是从一个不存在的类继承;相反,我们是从类
    Singleton
    继承的。模板可以在不完整的类型上实例化。(使用此类类型参数可以执行和不能执行的操作有几个规则。)

    例如,
    模板类Foo{}
    当然可以在任何类型上实例化,不会出现问题。更有趣的是,
    模板结构指针工厂{typedef T*type;}可以在任何类型上实例化,无论是否完整。在目前的情况下,CRTP中模板参数的目的仅仅是通知基类它的最终派生类型,因此这是完全正确的。

    1)不,不管您如何构造代码<顺便说一下,code>Singleton
    不是一个类:它是一个模板。由于完整的模板定义无论如何都必须在任何实例化站点上都是可访问的,因此您最好以内联方式定义所有内容

    2)
    class-DebugLog:public-Singleton
    可以。我们不是从一个不存在的类继承;相反,我们是从类
    Singleton
    继承的。模板可以在不完整的类型上实例化。(使用此类类型参数可以执行和不能执行的操作有几个规则。)


    例如,
    模板类Foo{}
    当然可以在任何类型上实例化,不会出现问题。更有趣的是,
    模板结构指针工厂{typedef T*type;}可以在任何类型上实例化,无论是否完整。在当前情况下,CRTP中模板参数的用途仅是通知基类其最终的派生类型,因此这是完全正确的。

    在这种情况下,必须使用指向T的指针:

    template<typename T>
    class Singleton {
    public:
        static T& getInstance() {
            static T * instance = NULL;
            if (!instance)
                instance = new T;
            return *instance;
        }
    };
    
    class DebugLog : public Singleton<DebugLog> {  //Question 2
        public:
            void doNothing() {}
    };
    
    模板
    单件阶级{
    公众:
    静态T&getInstance(){
    静态T*instance=NULL;
    如果(!实例)
    实例=新的T;
    返回*实例;
    }
    };
    类DebugLog:publicsingleton{//问题2
    公众:
    void doNothing(){}
    };
    
    在这种情况下,必须使用指向T的指针:

    template<typename T>
    class Singleton {
    public:
        static T& getInstance() {
            static T * instance = NULL;
            if (!instance)
                instance = new T;
            return *instance;
        }
    };
    
    class DebugLog : public Singleton<DebugLog> {  //Question 2
        public:
            void doNothing() {}
    };
    
    模板
    单件阶级{
    公众:
    静态T&getInstance(){
    静态T*instance=NULL;
    如果(!实例)
    实例=新的T;
    返回*实例;
    }
    };
    类DebugLog:publicsingleton{//问题2
    公众:
    void doNothing(){}
    };
    
  • 如果函数是在外部定义的,那么肯定会更干净 类,并使代码更易于阅读和维护。在这个 然而,在这种情况下,完整的类足够小,因此 不是很好,当然,因为我们要处理一个模板, 实际的定义仍然必须包含在每个翻译单元中 它使用它
  • < C++标准不涉及课堂上的“存在”(或任何东西)。 否则)。在模板实例化时,将查找名称
    DebugLog
    ,并发现它是一个类(因此是一个类型)。当时,, 这是一种不完整的类型,您只能做有限的事情 类型不完整。如果实例化的类模板 不做任何需要完整类型(和
    Singleton
    没有),那么就没有问题了。(请注意,只有 此时将实例化定义;类成员函数将 在使用它们之前不能实例化。)

    我可以补充一点,这本书仍然缺少一件重要的东西 您发布的代码:声明没有定义
    Singleton::instance
    。您仍然需要添加一个:

    template<typename T> T Singleton<T>::instance;
    
    template T Singleton::instance;
    
    某处

  • 如果函数是在外部定义的,那么肯定会更干净 类,并使代码更易于阅读和维护。在这个 然而,在这种情况下,完整的类足够小,因此 不是很好,当然,因为我们要处理一个模板, 实际的定义仍然必须包含在每个翻译单元中 它使用它
  • < C++标准不涉及课堂上的“存在”(或任何东西)。 否则)。在模板实例化时,将查找名称
    DebugLog
    ,并发现它是一个类(因此是一个类型)。当时,, 这是一种不完整的类型,您只能做有限的事情 类型不完整。如果实例化的类模板 不做任何需要完整类型(和
    Singleton
    没有),那么就没有问题了。(请注意,只有 此时将实例化定义;类成员函数将 在使用它们之前不能实例化。)

    我可以补充一点,这本书仍然缺少一件重要的东西 您发布的代码:声明没有定义
    Singleton::instance