单例模板作为 C++ 中的基类

JCR*_*ner 8 c++ singleton templates derived

根据C++ 单例设计模式, 我写了一个单例模板

template <typename T>
class Singleton
{
    public:
        static T& getInstance()
        {
            static T instance;
            return instance;
        }
    protected:
        Singleton() {}
        ~Singleton() {}
    public:
        Singleton(Singleton const &) = delete;
        Singleton& operator=(Singleton const &) = delete;
};
Run Code Online (Sandbox Code Playgroud)

然后我写了一个 Logger 单例(第一个)

class Logger                            // not derived Singleton<Logger>
{
    friend class Singleton<Logger>;
    private:
        Logger(){};
        ~Logger(){};                          
    public:
        void print(void){std::cout << "hello" << std::endl;}
};

int main(void)
{
    Singleton<Logger>::getInstance().print(); // use Singleton<Logger>
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但我也可以(第二个)

class Logger:public Singleton<Logger>    // derived Singleton<Logger>
{
    friend class Singleton<Logger>;
    private:
        Logger(){};
        ~Logger(){};                          
    public:
        void print(void){std::cout << "hello" << std::endl;}
};

int main(void)
{
    Logger::getInstance().print();      // use Logger
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

那么我的问题是

  1. 我的单例模板是否正确?
  2. 如果单例模板正确,那么两个 Logger 是否正确?
  3. 第一个和第二个的区别,哪个更好?

更新
在回答之后,我了解到第一个允许有多个记录器并且singleton该类似乎不需要。所以我丢弃了第一个。
关于第二个,我省略了析构函数,然后编译器会生成一个默认的内联公共的。这似乎更简洁,更有效。

class Logger:public Singleton<Logger>    // derived Singleton<Logger>
{
    friend class Singleton<Logger>;
    private:
        Logger(){};                       
    public:
        void print(void){std::cout << "hello" << std::endl;}
};
Run Code Online (Sandbox Code Playgroud)

Jar*_*d42 5

  1. 我的单例模板正确吗?

是的。

  1. 如果单例模板正确,那么两个 Logger 都正确吗?

由于复制构造函数,您的第一个代码片段允许有多个记录器。所以从这一点来说,这是不正确的。

  1. 第一个和第二个的区别,哪个更好?

如果您修复第一个代码片段以禁止复制构造函数,那么您只会错过基本的内容getInstance,并且您的Singleton类似乎不需要。

对于第二个片段,您甚至可以省略析构函数。