何かを宣言することは、何かを定義することと同じではありません。時には同時に両方を行うこともできますが、どちらかを宣言して定義する必要があります。
なぜですか?
標準ではそうだと言われていますが、なぜ標準でそう言いますか?
コンパイルとリンクの仕組みと関係があります。いくつかのソースファイル(a.cpp
とb.cpp
)といくつかのヘッダファイル(a.h
とb.h
)を持っていれば、それらをコンパイルしたいと思うでしょう。一般に、すべてのソースファイルを個別にコンパイルしてa.o
とb.o
にしてから、最後にリンクして最終的なプログラムを作成します。
は、私たちが持っていたと言う:
// a.h =========================
class A { static int n; };
// b.h =========================
class B { static int n; };
// a.cpp =======================
#include "a.h"
#include "b.h"
int foo() { return A::n + B::n; }
// b.cpp =======================
#include "a.h"
#include "b.h"
int bar() { return A::n - B::n; }
は#include
は、本質的にちょうど含むファイル内の他のファイルを貼り付けていることを覚えておいてください。だから我々はa.cpp
をコンパイルするときに、すべてのコンパイラが見てb.cpp
は次のとおりです。
A::n
と
B::n
がファイルをに行くべきオブジェクト
// a.cpp =======================
class A { static int n; };
class B { static int n; };
int foo() { return A::n + B::n; }
// b.cpp =======================
class A { static int n; };
class B { static int n; };
int bar() { return A::n - B::n; }
? a.o
またはb.o
? a.cpp
とb.cpp
の両方で宣言されているため、コンパイラはどこに置くべきか分かりません。それを両方に入れると、それを2回定義することになり、コンパイラはどちらを使うべきかを知りません(その場合、リンカはあなたに '複数定義されたシンボル'エラーを与えます)。
だから私たちには定義が必要です。定義はそれを置くために、ファイルオブジェクトを教えてくれる。
// a.cpp =======================
#include "a.h"
#include "b.h"
int A::n = 0; // A::n goes in a.o
int foo() { return A::n + B::n; }
// b.cpp =======================
#include "a.h"
#include "b.h"
int B::n = 0; // B::n goes in b.o
int bar() { return A::n - B::n; }
それはあなたがb.cpp
にa.cpp
または両方に両方入れている可能性があることを指摘しておきます。正確に1回定義されていれば問題ありません。
これは言語が求めているものですから。 –
[C++静的メンバー変数とその初期化]の重複可能性(http://stackoverflow.com/questions/4547660/c-static-member-variable-and-its-initialization) –