0

クラスがそれから派生するだけで自動的にシングルトンになるように、シングルトン クラスを作成しようとしています。

基本クラス:

 template <class T>
 class Singleton
 {
 private:
     static T* instance;
 public:

     static T* getInstance(void)
     {
         if(!instance)
             instance = new T;
         return instance;
     }

     static void release(void)
     {
         if(instance)
         {
             delete instance;
             instance = NULL;
         }
     }
 };

 template <class T>
 T* Singleton<T>::instance = NULL;

私の派生クラス:

#include <iostream>
#include "Singleton.h"

class MySingleton : public Singleton<MySingleton>
{
public:
    void helloWorld(void)
    {
        printf("Hello, World!\n");
    }
};

主要:

int main(int argc, const char * argv[])
{
    MySingleton* s = MySingleton::getInstance();
    s->helloWorld();
    return 0;
}

これは完全に機能しますが、デフォルトのコンストラクターを使用して MySingleton を構築できるため、実際のシングルトンではありません。もちろん、MySingleton の ctors をプライベートにして、Singleton をフレンドとして宣言することはできますが、基本クラスでそれを行う方法はありますか?

4

1 に答える 1

1

基本クラステンプレートはシングルトンオブジェクトを構築する必要があるため、具象クラスのコンストラクターにアクセスする必要があります。したがって、そのコンストラクターはパブリックであるか、基本クラスが具象クラスのフレンドである必要があります。具象クラスのパブリックCtorは誰でもアクセスできるため、コンパイル時に使用を禁止することはできません。ただし、実行時に1回だけ呼び出されることを保証できます。

template <class T>
class Singleton
{
  /* ... */
  static bool instantiating;
protected:
  Singleton()
  {
    if (!instantiating) //not called in instance() function
      throw std::runtime_error("Don't call me!");
  }

public:
  static T* getInstance()
  {
    intantiating = true;
    instace = new T();
    instantiating = false;
  }
};

template <class T>
bool Singleton<T>::instantiating = false;

注:-instantiatingここで使用している変数はスレッドセーフではありません-のtrue / false設定instantiatingは例外セーフではありません(newまたはT::T()スローされる可能性があります)-インスタンス変数としてのポインターの使用は安全ではなく、memleaksが発生しやすくなります。または参照を使用することを検討しshared_ptrてください(Meyersシングルトン)

于 2013-01-10T12:54:09.280 に答える