51

与えられたのは、静的メンバーを持つクラスです。

class BaseClass
{
public:
    static std::string bstring;
};

文字列は明らかにクラス外でデフォルトで初期化する必要があります。

std::string BaseClass::bstring {"."};

上記の行をクラスとともにヘッダーに含めると、symbol multiply definedエラーが発生します。またはcppであっても、別のファイルで定義する必要があります。include guardspragma once

ヘッダーで定義する方法はありませんか?

4

7 に答える 7

72

staticメンバー変数を複数回定義することはできません。変数定義をヘッダーに入れると、ヘッダーが含まれる各翻訳単位で定義されます。インクルード ガードは 1 つの翻訳単位のコンパイルにしか影響しないため、役に立ちません。

ただし、メンバー関数を定義できます。さて、一見すると、それが役に立たないように見えるかもしれませんが、もちろん、その関数はローカル変数を持つことができ、これらのいずれかへの参照を返すことはほとんどメンバー変数のように動作します。staticstaticstatic

static std::string& bstring() { static std::string rc{"."}; return rc; }

ローカルstatic変数は、この関数が最初に呼び出されたときに初期化されます。つまり、関数が最初にアクセスされるまで構築が遅延されます。もちろん、この関数を使用して他のグローバル オブジェクトを初期化すると、オブジェクトが時間内に構築されることも確認できます。複数のスレッドを使用する場合、これは潜在的なデータ競合のように見えるかもしれませんが、そうではありません (C++03 を使用しない限り): 関数ローカルstatic変数の初期化はスレッドセーフです。

于 2013-09-17T22:38:51.350 に答える
2

いいえ、ヘッダーで行うことはできません-少なくとも、ヘッダーがソースファイルに複数回含まれている場合はそうではありません。そうでない場合、そのようなエラーは発生しません。.cpp ファイルの 1 つに貼り付けるだけで完了です。

于 2013-09-17T22:30:59.247 に答える
1

更新:以下の私の答えは、質問で提案された方法でこれを行うことができない理由を説明しています。これを回避する答えが少なくとも 2 つあります。問題を解決する場合としない場合があります。


bstring静的メンバーは、特定のメモリ アドレスにリンクする必要があります。これを行うには、単一のオブジェクト ファイルに表示する必要があるため、単一のcppファイルに表示する必要があります。ヘッダー ファイルが複数のファイルに含まれている可能性があるため、これが確実に行われるように 'sで遊んでいる#ifdef場合を除き、ヘッダー ファイルで目的の処理を行うことはできませんcpp

于 2013-09-17T22:31:41.933 に答える