2

重複の可能性:
C++ - クラス定義で静的 const 整数メンバーを定義する

注: 同様の問題に関するいくつかの質問が現存していますが、私はそれらの多くを確認しましたが、この動作を説明する答えが見つかりません:

次のようなコードがあるとします (ヘッダーファイル内) 。

class Foo {
    static const int TEST = 33;

    public:
    void willItWork(void) {
        printf("%d", std::max(TEST, 75));  // embedded platform, no streams
    }
};

int main(void) {
    Foo tester;
    tester.willItWork();
}

これはコンパイルされますが、リンクされません。リンカーエラーが発生します

エラー: L6218E: 未定義のシンボル Foo::TEST (foo.o から参照)。

値を外部関数に渡すだけで問題が発生するようです。TESTクラス内の通常の式または関数での使用は正常に機能します。代わりに次のように書くwillItWork()

void willItWork(void) {
    int diff = TEST - 23;
    printf("%d", diff);
}

エラーはありません。

これに関するC++標準を参照する別の質問を見つけました(セクション9.4.2):

静的データ メンバーが const 整数型または const 列挙型の場合、クラス定義でのその宣言は、整数定数式である const-initializer を指定できます。

私がしたことは「規則の範囲内」にあるように見えるので、この奇妙な振る舞いについて考えられる説明を誰か思いつくことができますか?

私は ideone で同様のコードを試しましたが、問題はありませんでした (ただし、正確な構造を模倣することはできません。つまり、そこにヘッダー ファイルがあります)。これは、私が使用しているリンカーがここの標準に完全に準拠していないということですか?

どんな洞察も大歓迎です。いつでもより多くの情報を提供することもできます。

4

2 に答える 2

4

コンパイラがstaticメンバー変数のアドレスが必要であると判断した場合、たとえば、ある時点で変数を参照にバインドする場合、対応する未定義のシンボルが作成され、メンバーを定義する必要があります。

int const foo::TEST;

(1 つの翻訳単位で)。コンパイラが値にしかアクセスしない場合は、オブジェクトを定義しなくても問題ありません。型を an にする必要がない限り、代わりにintan を使用してenum、メンバーを定義する必要を避けることができます。

enum { TEST = 33 };

私が正しく思い出せば、探すべき標準の用語はodr-usedです。

于 2012-11-15T01:47:50.637 に答える
3

std::max値ではなく、参照によって引数を取ります。static const への参照をバインドするには、値だけでなく、実際のオブジェクトが必要です。

于 2012-11-15T01:46:05.323 に答える