Skip to main content

シングルトンとやらについて

シングルトンパターン

シングルトンパターンについては、そんなに語ることもないと思うけれども、そのプログラムの中でインスタンスを1つに統一して使うデザインパターンのこと。

ゲームで言うと、ゲームの中でプレイヤーキャラを1体だけだして、2人目以上を登場させようとしたら自動的に出てこないように抑制できる仕組みです。

作ってみるよ

まずは普通にクラス作った場合を見てみよう(見る必要ない気もするけど)

ソースコード

#include 

class Hero
{
private:
	std::string name;
public:
	Hero()
		: name("AnPanMan")
	{
		std::cout 
実行結果

res1.png

こんな感じで、いくらでも同じキャラのインスタンスが生成できます(まぁインスタンスってそういう話だったよね)。
次に、このワールド(世界)にアンパンマンは一人しか存在しないように変更してみる。

シングルトンパターンとやらを試してみる

シングルトンのつくりかた♡
  1. (オプション)クラスを継承不可に指定
  2. コンストラクタを private に指定する 2.静的なポインタ変数を宣言する
    • んで、こいつにインスタンスのアドレスを格納する
    • 後は、この変数だけが唯一のインスタンスになるように頑張る
  3. 静的なポインタを初期化する
  4. インスタンスを返す静的な GetInstance 関数を実装する
    • 静的な変数 == nullptr
      • ⇒新しくインスタンスを生成する
    • 静的な変数 != nullptr
      • ⇒静的な変数(のポインタか参照)を返す

0. (オプション)クラスを継承不可に指定

クラス宣言するときに、後ろにfinalキーワードを付加するとそのクラスは継承できない!とコンパイラに伝えることができるよ。


class Hero final
{
private:
//省略
};                                                               

1. コンストラクタを private に指定する


class Hero
{
private:
	std::string name;
public:
	Hero(){//省略
    }
    //省略
}

これを ↓ 以下の様に変更する!これで、勝手にコンストラクタが呼べなくなる=好きにインスタンスを生成することができなくなる。
じゃぁどうやってインスタンス作るの?ってことになるが、それは次。


class Hero final
{
//省略
private:
    std::string name_;
	Hero()
		: name("AnPanMan")
	{
		std::cout 

2.静的なポインタ変数を宣言する

お外から見えないところ=privateなところに、```static Hero* s_hero_;````みたいな感じで、静的なメンバ変数を生成


class Hero final
{
private:
	//クラスの静的なポインタを宣言する
	static Hero* s_hero_; //👈これがスタティックなポインタ変数
	std::string name;	
	Hero()
		: name("AnPanMan")
	{
		std::cout 

3. 静的なポインタを初期化する



class Hero final
{
private:
//盛大に省略
};
//どこかグローバルスコープなところで
Hero* Hero::s_hero_ = nullptr;//👈静的メンバ変数の定義

4. インスタンスを返す静的な GetInstance 関数を実装する

ここが一番のポイント!
nullptrで初期化された静的変数をGetInstanceが呼ばれるたびに確認し、インスタンスが既に存在していれば、そのインスタンスを返す。
nullptrだった場合は、新しいインスタンスを作って、それを返す。
逆に言うと、nullptrだった時だけインスタンスが生成されるってだけ。


public:
	static Hero& GetInstance();//👈静的な参照を返す関数(宣言文)
};

// Hero クラスのインスタンスを取得する
Hero* Hero::GetInstance()
{
	if (s_hero_ == nullptr) //インスタンスが無かったら
	{
		s_hero_ = new Hero(); //新しく生成
	}
	return *s_hero_;//インスタンスがあればそれを返す
}                      

実行してみようズ

プログラムの全体像と、実行のためのmain関数を以下に示す。  


#include 


class Hero final
{
private:
	// Graphics クラスの静的なポインタを宣言する
	static Hero* s_hero_;
	std::string name_;	
	Hero()
		: name_("AnPanMan")
	{
		std::cout name_ 

実行結果

GetInstanceした時に、ついでに、インスタンスのアドレスを表示するようにしてみた。 つまり、同じインスタンスが参照されていれば、同じアドレスが毎回帰ってくるし、毎回作っちゃっていれば、毎回違うアドレスになるはずだよね!

res2.png

2回目以降のGetInstanceでは、初めに作られたインスタンスが参照されて返されていることがわかる!