静的メンバ
オブジェクトのないメンバ
これまで、クラス型のオブジェクトには全てのメンバが割り当てられました
オブジェクトごとにメンバ変数が割り当てられ、メンバ変数はオブジェクト間で関係ありません
しかし、あるクラスの全てのオブジェクトが
一つの変数を共有したいとすれば、困ります
グローバル変数を使うこともできますが、それはオブジェクト指向プログラムに反した行為です
そのような場合は、静的メンバ変数を用います
静的メンバ変数は、全てのオブジェクトが共有するクラス内グローバル変数と呼べます
これは、オブジェクトごとにコピーが作られるようなことはなく
つねにクラスに一つしか存在しないメンバなのです
静的メンバ変数の宣言には static キーワードを使います
static var;
var は、静的メンバ変数を宣言します
ただし、この時点ではまだ変数は存在していません
静的メンバ変数は、クラスの外で変数を再宣言しなければならないのです
変数の定義は、クラスをスコープ解決演算子で指定して再宣言します
静的メンバ変数は、オブジェクトが生成される以前から存在します
そのため、再宣言するときに初期値を与えることも可能です
初期値を与えなかった場合、デフォルトで0が入ります
また、静的メンバ変数はオブジェクトを持たないので
オブジェクトが無くても、次のように直接アクセスすることができます
class-name::member;
class-name にはクラス名を指定します
member は、アクセスする静的メンバ変数です
#include<iostream>
using std::cout;
class Kitty {
public:
static char *str;
};
char * Kitty::str = "Kitty on your lap";
int main() {
cout << Kitty::str;
return 0;
}
Kitty クラスのメンバ変数 str は静的メンバです
この静的メンバ変数は、実際にひとつしかないので
このように、クラス名を指定すればグローバル変数のようにも扱えます
一般的な用途としては、非公開メンバとして静的メンバを用いて
オブジェクト間の同期をとるなどの目的に使用するなどが考えられます
静的メンバ変数には、オブジェクトからもアクセスすることができます
いくつオブジェクトがあっても、静的メンバ変数は一つで、全てのオブジェクトに共有されます
#include<iostream>
using std::cout;
class Kitty {
static char *str;
public:
char * getStr() { return str; }
};
char * Kitty::str = "Kitty on your lap\n";
int main() {
Kitty obj1 , obj2;
cout << "obj1.str = " << obj1.getStr();
cout << "obj2.str = " << obj2.getStr();
return 0;
}
このプログラムは有効です
obj1 も obj2 も同じ str にアクセスしています
そのため、getStr() 関数で出力される文字は両方とも Kitty on your lap です
静的メンバ関数
静的メンバ変数に対して、静的メンバ関数も存在します
静的メンバ関数はクラスをスコープとするグローバル関数のような存在です
このメンバ関数は、全てのオブジェクトに共有される関数で
オブジェクトが無くても、クラス名を指定すればアクセスすることができます
静的メンバ関数は、通常のメンバ変数にアクセスすることはできません
これは、静的メンバ関数がthisポインタを持たないためです
仮想静的メンバ関数というものを作ることもできず
また、constやvolatile属性を付加した宣言もできません
#include<iostream>
using std::cout;
class Math {
public:
static max(int var1 , int var2) {
if (var1 > var2) return var1;
else return var2;
}
};
int main() {
cout << Math::max(100 , 101);
return 0;
}
静的メンバ関数 max() は、数学アルゴリズムを管理するMathクラスのメンバと想定します
二つの数のうち、大きいほうを返す関数 max() はオブジェクトを必要としません
しかし、分類上数学クラスに割り当てたほうが、オブジェクト指向プログラムとしてあるべき姿です
このような場合は、上のプログラムのように静的メンバ関数として実装するべきです
簡単な処理をするためにオブジェクトを初期化するなどの処理を行うのは面倒で不合理です
当然、静的メンバ関数はオブジェクトを介してでもアクセスすることができます
しかしこの場合でも、オブジェクトのthisポインタが渡されることはありません