ウィキペディアから直接:
一般に、翻訳単位にはクラス型の定義が 1 つしか含まれません。この例では、クラス型 C の 2 つの定義が同じ翻訳単位に含まれています。これは通常、ヘッダー ファイルが適切なヘッダー ガードなしで同じソース ファイルによって 2 回インクルードされた場合に発生します。
class C {}; // first definition of C
class C {}; // error, second definition of C
次の、S へのポインタの作成または S への参照を取る関数の定義は、S の型が完全である必要がないため、正当な構造の例です。したがって、定義は必要ありません。
型 S のオブジェクトの定義、型 S の引数を取る関数、または sizeof 式での S の使用は、S が完全でなければならないコンテキストの例であり、したがって定義が必要です。
struct S; // declaration of S
S * p; // ok, no definition required
void f(S&); // ok, no definition required
void f(S); // ok, no definition required
S f(); // ok, no definition required
S s; // error, definition required
sizeof(S); // error, definition required
複数の定義
場合によっては、型またはテンプレートの定義が複数存在することがあります。複数のヘッダー ファイルとソース ファイルで構成されるプログラムには、通常、1 つの型の定義が複数ありますが、翻訳単位ごとに複数の定義はありません。
プログラムに 1 つの型の定義が複数含まれている場合、各定義は同等でなければなりません。
static const データ メンバの定義
標準化前の C++ では、すべての静的データ メンバーはクラス外で定義する必要がありました。ただし、C++ 標準化プロセス中に、static const 整数メンバーに対するこの要件を解除することが決定されました。その意図は、次のような使用を許可することでした。
struct C
{
static const int N = 10;
};
char data[C::N]; // N "used" without out-of-class definition
N の名前空間スコープ定義なし。
それにもかかわらず、1998 年の C++ 標準の文言では、メンバーがプログラムで使用される場合、依然として定義が必要でした。これには、sizeof または typeid のオペランドとして以外の場所に現れるメンバーが含まれ、事実上、上記の形式が正しくありませんでした。
これは欠陥として識別され、クラス外の定義を必要とせずに、そのようなメンバーを定数式が必要な場所に表示できるように文言が調整されました。これには、配列境界、ケース式、静的メンバー初期化子、非型テンプレート引数が含まれます。
struct C
{
static const int N = 10;
static const int U = N; // Legal per C++03
};
char data[C::N]; // Legal per C++03
template<int> struct D;
template<> struct D<C::N> {}; // Legal per C++03
ただし、整数定数式が必要な場所以外の場所で static const 整数メンバーを使用するには、定義が必要です。
struct C
{
static const int N = 10;
};
int main()
{
int i = C::N; // ill-formed, definition of C::N required
}
この要件は、口語的に C++0x と呼ばれる次期 C++ 標準で緩和される予定です。