Lyの日常

主が楽しくプログラムをカキカキするブログ

シングルトンパターン in C++

ふっ、とうとうここまでたどり着いてしまったか
そうだ、この私がシングルトンパターンだ!

*クラスを勉強し始めた人向けです

あっはい
どうもLyです
シングルトン便利です、ω、

シングルトンの利点はクラスのインスタンス(クラス内のデータ)を
グローバルと同じように扱えること
あとはそのクラスが唯一になること

始めにSingletonクラスを宣言してみましょう

class Singleton {};

int main() {
  Singleton singleton;
  // このままではSingletonクラスを複製できてしまう
  // Singleton singleton2;
}

クラスが宣言されたとき呼ばれるのは
コンストラクタです
クラスと同じ名前の関数です
基本的にこのコンストラクタでデータの初期化をしますね

class Singleton {
public:
  Singleton(){} // ←こいつですね
};

では、さきほどのようにコンストラクタを書かない場合どうなるのか
それはコンパイラが勝手にpublicな空間に作成してくれます

コンストラクタはクラスが宣言されたとき呼ばれます
逆にコンストラクタが無いと宣言が出来なくなります

// コンストラクタをprivateに置く
class Singleton {
private:
  Singleton(){}
};

int main() {
  Singleton singleton; // err
}

クラスが宣言できないとそもそもクラスにアクセスできない!
というわけでもなく
クラスのpublicな空間にstaticな関数をおけば実はアクセスできます

class Singleton {
private:
  Singleton(){}

public:
  static Singleton& getInstance {
    static Singleton singleton;
    return singleton;
  }
};

やっていることはいたって単純で
クラスの中でクラスを作成しているだけです
そして作成したクラスを出力する関数を作っています

クラスのデータにアクセスする場合は
こんな風にアクセスします

int main() {
  Singleton::getInstance();
}

Singleton::getInstance()
これは
getInstance関数の中で宣言されたsingletonと同等です

なので、例えばPlayerクラスをシングルトンにした場合

class Player {
private:
  Player(){}
  
  Vector2f pos;
public:
  static Player& getInstance() {
    static Player player;
    return player;
  }

  Vector2f getPos() { return pos; }
};

int main() {
  Vector2f player_pos;
  player_pos = Player::getInstance().getPos();

  std::cout << "プレイヤーの現在地 x("
            << player_pos.x << ") y("
            << player_pos.y << ") \n";
}

という風にアクセスします

もっと詳しくシングルトンについて知りたい場合は
WikiへGO!
((ってググったら真っ先にWiki出ると思うけどw