2012-03-20 13 views
2

わかっているように、クラス構造内で整数constスタティックメンバを初期化することは可能です。例えば、int配列のサイズとして使用できます。 次のコードを見て:なぜクラス内で初期化されたconstスタティックメンバを定義する必要があるか

class MyClass{ 
static const int num = 100; 
int elems[num]; 
... 
}; 

しかし、我々はまだクラス定義の外でメンバーNUMを定義する必要があります。

const int MyClass::num; 

私たちは、このようにしなければならない理由を私は知りません。 誰かが私にその理由を教えてもらえますか? ありがとうございました。 Visual Studio 2008にも

#include <iostream> 
using namespace std; 

class MyClass{ 
public: 
MyClass() 
{ 
    cout << "instruct class MyClass!" << endl; 
} 
static const int num = 100; 
int elems[num]; 
}; 

//const int MyClass::num; 

int main() 
{ 
MyClass a; 
const int *b = &(a.num); 
cout << "&(a.num): " << &(a.num) << endl; 
cout << "a.num: " << a.num << endl; 
cout << "*b: " << *b << endl; 
} 

それが実行されます:

はまた、私は次のコードを記述

enter image description here

しかし、私は、コードを削除したことを明確メンバーNUMクラス外。

私は非常に混乱しています。誰かが私のためにそれを解釈できますか?

答えて

5

クラスの初期化は、主に定数式を取得するために使用されます。このためには価値が重要です。オブジェクトのアドレスを取得するか、参照にバインドすると、コンパイラはオブジェクトの場所も必要とします。これは効果的に定義が提供するものです。

+1

しかし、コンパイラはテンプレートの静的メンバーや複数のファイルに定義されていても単一のアドレスが必要なインライン関数を処理するのと同じ方法で処理できます。 –

+0

@JamesKanze:テンプレートの静的メンバーの場合、暗黙的なインスタンス化がこれに対して機能しないため、実際にはかなり迷惑な定義が必要です。インライン関数で静的変数のように振舞うようにすることができます。私が理解していることは、リンク時に破棄される弱いシンボルを持つ関数を作成することによってこれらの作業が行われることです。しかし、コンパイラは存在していると主張することはできませんが、言語は現在のところ定義を必要とします。 –

+0

私は知っています。私はちょうど技術的には、それを必要としないコンパイラ技術が他の文脈でも必要であるので、定義を必要としないことは問題ではないと言っています。 –

4

あなたはあなたのコードは、それがaddress.Thisがアウト・オブ・クラス定義として知られています要する場合にのみ、cppのファイルにクラスの外num静的定数を定義する必要があります。
コードのアドレスがnumでない場合、クラス初期化は正常に動作します。

理由:

Bjarne states

「C++は、すべてのオブジェクトは、独自の定義を持っていることを必要とすることにルールがあることを必要とするエンティティのC++許可されている場合は、クラス定義を破られることになります。オブジェクトとしてメモリに格納されます。

static constの整数だけをコンパイル時定数として扱うことができます。コンパイラは整数値がいつでも変更されないことを知っているので、独自のマジックを適用して最適化を適用することができます。コンパイラはそのようなクラスメンバを単にインライン化します。つまり、メモリに格納されません。そのような変数には、Bjarneが述べた上記の規則に対する例外が与えられます。

static const積分値がIn-Class Initializationを持つことができても、そのような変数のアドレスは取ることができません。コンパイラがそれらをメモリに置く必要があるため、静的メンバーのアドレスを取ることができます。

+0

最後に私は理解しています。本当にありがとうございます!私はあなたの返信にとても感謝しています! – XiaJun

関連する問題