2つの静的変数を持つクラスAがあります。関係のない静的変数を次のように初期化したいです:
#include <iostream>
class A
{
public:
static int a;
static int b;
};
int A::a = 200;
int a = 100;
int A::b = a;
int main(int argc, char* argv[])
{
std::cout << A::b << std::endl;
return 0;
}
出力は200です。だから、誰が私に理由を教えてもらえますか?
ルックアップルールによればそれは正しいです。 [basic.lookup.unqual]/1 言います:
クラスXの静的データメンバーの定義で使用される名前(静的メンバーの限定IDの後)は、Xのメンバー関数で名前が使用されたかのように検索されます。[注:[class.static.data ]は、静的データメンバーの定義での名前の使用に関する制限についてさらに説明します。 —メモを終了]
修飾されていないa
が検索されるためas ifあなたはメンバー関数の中にいるので、最初にメンバーA::a
を見つけなければなりません。 A::a
とA::b
の初期化順序はルックアップに影響しませんが、結果の定義の精度に影響します。
だから、誰も私に理由を教えてもらえますか?
これは basic.scope.class/4 に明記されています。
クラス定義の終わりまで、またはそれを超えて宣言されている可能性のあるスコープは、リージョンにも拡張されますメンバーが字句的にクラス外で定義されていても(このには静的データが含まれます)メンバー定義、ネストされたクラス定義、およびメンバー関数の定義を含み、メンバー関数本体と、declarator-idに続くそのような定義の宣言子部分の任意の部分(パラメーター宣言節を含む)およびデフォルトの引数)。
したがって、あなたが持っているとき
int A::a = 200;
int a = 100;
int A::b = a; // note the '::' scope resolution operator
// OUTPUT: 200
a
は実際にA::a
を参照します。これは、クラススコープがextendedであるためですA::b
によって。
あなたが持っている場合とは異なり:
int A::a = 200;
int a = 100;
int b = a; // note b is not A::b
// i.e. without the '::', scope resolution operator
// OUTPUT: 100
a
は(グローバル)::a
を参照します。ここでb
はclass A
のメンバーではないため、
i.eクラススコープ拡張はありません。
メンバーのdeclarator-id、および名前に続く静的メンバーの定義でunqualified-idが使用されている場合lookup([basic.lookup.unqual])は、unqualified-idがメンバーのクラス(またはメンバーのクラスの基本クラス)の静的メンバー、列挙子、またはネストされた型を参照していることを検出します。 )、unqualified-idはqualified-id式に変換されます、nested-name-specifierはメンバーが参照されるクラススコープを指定します。 [注意:非静的データメンバーおよび非静的メンバー関数の使用に関する制限については、[expr.prim.id]を参照してください。 —メモを終了]
それはあなたの状況でunqualified-idがqualified-id式に変換されると言います。
int A::b = a;
修飾IDを設定できますが、このようなネストされた名前指定子はありません。
int A::b = ::a;
名前の検索により、a
がA::a
として解決されるためです。これを行うには、スコープを手動で解決する必要があります。
int A::b = ::a;
// ^ Global scope resolution