ホームに戻る
関連 :
目次 :
static修飾とは
修飾する対象が 静的・永続的 であることを示すこと。
プログラムの開始から終了までメモリ(RAM)を占有し続けるとともに、グローバルスコープの関数・変数に適用した場合は、宣言されたファイルの外からのアクセスを制限する効果を持つ。
稀に「不変(const)」との混同がみられるが、まったく異なる概念である。
static修飾の類型
グローバル関数を修飾する
グローバルスコープの関数を修飾すると、 その関数が宣言されたファイル以外からはアクセスできなくなる 。即ち、extern修飾とは排他である。
(Hoge.c)
// 関数を static 修飾
static void HogeFunc()
{
:
}
void DoSomething_Hoge()
{
// 同じファイルなのでアクセス可能
HogeFunc();
}
(Fuga.c)
void DoSomething_Fuga()
{
// ファイルを跨ぐためアクセス不可 ⇒ コンパイルエラー
HogeFunc();
}
グローバル変数を修飾する
グローバル関数と同様、 その変数が宣言されたファイル以外からはアクセスできなくなる 。
(大域変数を用いるとデータの一貫性を保つことが困難となるため、グローバル変数はすべてこの形で用いるべきである。)
(Hoge.c)
// 変数をstatic修飾
static int staticVal = 3;
void DoSomething_Hoge()
{
// 同じファイルなのでアクセス可能
Func(staticVal);
}
(Fuga.c)
void DoSomething_Fuga()
{
// ファイルを跨ぐためアクセス不可 ⇒ コンパイルエラー
staticVal = 4;
}
const修飾との併用
修飾された変数が不変(定数)になるとともに、 ROMに配置される 。
⇒ RAM(スタック)の使用量を削減できる。
ローカル変数を修飾する
ローカル変数を修飾した場合、 関数の呼び出しを跨って値を保持し続ける 。
void Func()
{
static int staticVal = 3; //< 変数宣言・初期化(初期化は初回しか実行されない)
printf("staticVal = %d\n", staticVal);
++staticVal;
}
void main()
{
Func(); //< staticVal が 3 で初期化され、インクリメントされて 4 になる
Func(); //< 呼び出しを跨いで staticVal の値を保持(関数開始時点で staticVal == 4)
Func();
}
実行結果
staticVal = 3
staticVal = 4
staticVal = 5
const修飾との併用
グローバル変数と同様、定数となり ROMに配置される 。
(C++)クラスメンバを修飾する
関数・変数が 特定のインスタンスに縛られない永続的、かつ唯一のものとなる 。
このため、 インスタンスを生成せずに参照することができる 。(参照する際はスコープ解決演算子 :: を用いる)
class CHoge
{
private:
static int val;
public:
static void DoSomething1(int i) { val = i; }
static void DoSomething2(int i) { DoSomething1(i); }
}
void main()
{
// CHoge の静的メンバ関数をコール
CHoge::DoSomething2(4);
}
デザインパターンの一つである「シングルトン」は、この静的メンバを用いて実現される。
メンバ変数の修飾
クラスインスタンスを複数作成した場合でも非静的メンバ変数(の実体)はプログラム中で唯一であり、あるインスタンスを介して値を変更した場合、他のインスタンスからは同じ値が読み出せる。
(そもそもインスタンスとは別に存在し、特定のインスタンスに束縛されない。)
メンバ関数の修飾
静的メンバ関数からは静的でないメンバへのアクセスは原則不可で、static修飾された関数、または変数のみ操作可能である。
静的メンバ関数は、通常の関数ポインタに代入可能となる 。
(逆に、静的でないメンバ関数は通常は代入できない。詳細はメンバ関数ポインタを参照。)
静的メンバ関数はインスタンスではなくクラスに束縛されるため、「クラスメソッド」とも呼ばれる。
(非静的メンバ関数はインスタンスに束縛されるため「インスタンスメソッド」と呼ばれる。)