C++ 中作为基础 class 的单例模板

singleton template as base class in C++

根据C++ Singleton design pattern我写了一个单例模板

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;
};

然后写了一个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;
}

但我也可以(第二个)

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;
}

那么我的问题是

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

更新
在回答之后,我了解到第一个允许有多个记录器并且 singleton class 似乎 unneeded.SO 我 discard 第一个。
关于第二个,我 省略了 析构函数,然后编译器将生成一个默认的内联 public 析构函数。这样看起来更简洁高效。

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

1)你的单例模板是正确的。

2) 你的两个记录器都是正确的。但第二个是不好的做法。因为没有必要从单例模板派生记录器。 您可以通过将此行放在第二行来检查它:

Singleton<Logger>::getInstance().print();

工作正常。

3)第一个更好

  1. Is my singleton template correct?

是的。

  1. If singleton template is correct, the both Logger is correct?

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

  1. The difference between the first one and the second one, which one is better?

如果您修复第一个片段以禁止也复制构造函数,那么您只会错过基本的 getInstance 而您的 Singleton class 似乎不需要。

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