2009-08-25 10 views
7

次の2つのファイルをリンクできませんでした。「静的」キーワードを削除しても大丈夫です。 g ++でテスト済み。 readelfでオブジェクトファイルをチェックすると、静的メンバーがグローバルオブジェクトシンボルとしてエクスポートされているように見えますが、ローカルオブジェクトでなければならないと思います...?静的メンバーの複数定義ですか?

static1.cpp

class StaticClass 
{ 
public: 

    void setMemberA(int m) { a = m; } 
    int  getMemberA() const { return a; } 

private: 
    static int  a; 

}; 
int StaticClass::a = 0; 
void first() 
{ 
    StaticClass statc1; 
    static1.setMemberA(2); 
} 

エラー情報でstatic2.cpp

class StaticClass 
{ 
public: 

    void setMemberA(int m) { a = m; } 
    int  getMemberA() const { return a; } 

private: 
    static int  a; 

}; 
int StaticClass::a = 0; 
void second() 
{ 
    StaticClass statc1; 
    static1.setMemberA(2); 
} 

/tmp/ccIdHsDm.o:(.bss+0x0):複数の `StaticClass :: a 'の定義

答えて

16

各ソースファイルに同じ名前のローカルクラスを作成しようとしているようです。 C++では、あなたは匿名の名前空間にローカルクラスをカプセル化することができます

namespace { 
class StaticClass 
{ 
public: 

    void setMemberA(int m) { a = m; } 
    int  getMemberA() const { return a; } 

private: 
    static int  a; 

}; 
int StaticClass::a = 0; 
} // close namespace 

void first() 
{ 
    StaticClass statc1; 
    static1.setMemberA(2); 
} 
+0

@Ropez:うまく動作します。ありがとう:) –

+0

私はロペスの答えは、あなたが探していた解決策を与えているようだので、状態の悪い感じ。とにかく彼の+1にチェックマークを移動してください。 –

+0

@Litb、どちらも正しいです:)もっと説明しました。 –

0

StaticClassには、すべてのクラスインスタンスで共有される静的変数であるaを格納する場所が必要です。これには2つの行があり、各ファイルに1つずつあります。 1つを削除すると、リンカーエラーが修正されます。

9

以下は、静的データメンバーの定義です。それは、コンパイルされてリンクされた1つのファイルでのみ発生する必要があります。

int StaticClass::a = 0; 

あなたが複数のそのような定義を持っている場合は、firstと呼ばれる複数の機能を持っていたかのように、それはあります。彼らは衝突し、リンカーは不平を言うでしょう。

静的メンバーを名前空間スコープ変数に適用された静的変数と間違えていると思います。名前空間レベルでは、staticは変数または参照内部リンケージを与えます。しかし、クラスのスコープレベル(メンバーに適用される場合)では、各オブジェクトの代わりにクラスに個別にバインドされた静的メンバーになります。それは、もはや「静的」という意味のCとは関係がありません。

+0

問題は、私は、リンカは、そのローカルのオブジェクト・ファイルに変数をリンク知っておくべきだと思うということです、これはローカル静的変数ではなく、グローバルな静的であるため、 1。 –

+0

ローカルでもグローバルでもありません。それはクラスのメンバーです。 http://en.wikipedia.org/wiki/Class_variable –

+2

@arsaneロケールクラスが必要な場合は、匿名の名前空間に配置する必要があります。これを書くと、static1.cppのStaticClassはstatic2.cppのStaticClassと同じクラスになります。クラスがヘッダーに定義されていないと言う前に、マクロプロセッサーはテキストのインクルードで動作することを忘れないでください。 – AProgrammer

2

声明

int StaticClass::a = 0; 

は、実際には一度だけ書かれるべき理由です、変数用のストレージを割り当てます。

staticキーワードの2つの異なる用途を混乱させる可能性があります。 「内部リンケージの使用」を意味するCスタティックでは、変数または関数の名前が定義されている変換単位の外には見えないことを意味します。

クラスでは、クラスメンバーを定義するためにstaticが使用されます。これは、クラスの特定のインスタンスを参照しない変数またはメソッドです。この場合、静的変数の記憶域は、(インスタンスの一部ではないため)どこかに配置する必要がありますが、1つの場所にのみ配置する必要があります。