まず、あなたの誤解は名前空間とは何static
の関係もありません。それはについてだけです。この回答の残りの部分でtestNum
は、名前空間にあるという事実は無関係であるという理由だけで参照します。
また、おそらく関数と呼ばれる別のファイルがあり、関数test.cpp
を含みtest.h
、定義していると仮定しますsetNum
。
名前空間スコープの変数または関数(つまり、クラスメンバーではない、または関数のローカルではない)が宣言されstatic
ている場合、それはエンティティの名前がそのファイルの内部にあることを意味します。正式には「内部リンク」があります。つまり、名前で参照したり、他のファイルからリンクしたりすることはできません(ポインターを介して間接的に参照したり、別の関数に引数として渡すことで参照できます)。ファイルが定義するstatic int testNum
と、各ファイルには、他のすべてのファイルとは異なる、その名前の独自の内部変数がありtestNum
ます(実際、1つのファイルが持つ可能性がstatic int testnum
あり、別のファイルが持つ可能性があり、static double testnum
別のファイルが持つ可能性がありstatic char* testNum
ます。これらはすべて、各ファイルに対して別個で内部的なものになります)。そのような定義をヘッダーに入れると、ヘッダーを含むすべてのファイルに独自のがありtestNum
ます。
したがってstatic
、ヘッダーの変数には、を含むすべてのファイルで呼び出される異なる変数があります。つまり、1つのファイルに設定し、それを使用する別のファイルで関数を呼び出すと、同じ名前の別の変数が参照されます。testNum
test.h
testNum
testNum
このため、ヘッダーで非定数static
変数を宣言することはほとんどの場合間違っています。
これがないと、を含むすべてのファイルに変数static
の定義がありますが、これは許可されていません。すべてのエンティティは、プログラムで1回だけ定義する必要があります。これを解決する方法は、ヘッダーで変数を宣言することですが、定義はしません。これは、コンパイラーに変数を指示することによって行います。testNum
test.h
extern
extern int testNum; // N.B. no "= 1" here
これは、コンパイラに「外部リンケージ」と呼ばれる変数があることを示しているtestNum
ため、コードが参照する場合、testNum
常に同じ変数を意味します(すべてのファイルで異なるエンティティである内部リンクを持つ名前ではありません)。extern
変数を宣言した後は、プログラムのどこかに正確に1つの定義が提供されていることを確認する責任があるため、正確に1つのファイル(つまり、複数のファイルに含まれるヘッダーではない)で定義します。
int testNum = 1;