Class static variable initialization order
C++ScopeLanguage LawyerC++ Problem Overview
I have a class A which has two static variables. I'd like to initialize one with another, unrelated static variable, just like this:
#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;
}
The output is 200. So, could anyone tell me why?
C++ Solutions
Solution 1 - C++
That's correct according to the lookup rules. [basic.lookup.unqual]/13 says:
> A name used in the definition of a static data member of class X > (after the qualified-id of the static member) is looked up as if the > name was used in a member function of X. [ Note: [class.static.data] > further describes the restrictions on the use of names in the > definition of a static data member. — end note ]
Since the unqualified a
is looked up as if you are inside a member function, it must find the member A::a
first. The initialization order of A::a
and A::b
doesn't affect the lookup, though it affects how well defined the result is.
Solution 2 - C++
> So, could anyone tell me why?
This is clearly stated in basic.scope.class/4, emphasis mine:
> The potential scope of a declaration that extends to or past the end > of a class definition also extends to the regions defined by its > member definitions, even if the members are defined lexically outside > the class (this includes static data member definitions, nested class > definitions, and member function definitions, including the member > function body and any portion of the declarator part of such > definitions which follows the declarator-id, including a > parameter-declaration-clause and any default arguments).
Thus, when you have
int A::a = 200;
int a = 100;
int A::b = a; // note the '::' scope resolution operator
// OUTPUT: 200
a
actually refers to A::a
because the class scope is extended by A::b
.
Unlike if you have:
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
would refer to the (global) ::a
since b
here is not a member of class A
,
i.e. no class scope extension.
Solution 3 - C++
> If an unqualified-id is used in the definition of a static member following the member's declarator-id, and name lookup ([basic.lookup.unqual]) finds that the unqualified-id refers to a static member, enumerator, or nested type of the member's class (or of a base class of the member's class), the unqualified-id is transformed into a qualified-id expression in which the nested-name-specifier names the class scope from which the member is referenced. [ Note: See [expr.prim.id] for restrictions on the use of non-static data members and non-static member functions. — end note ]
It says the unqualified-id is transformed into a qualified-id expression in your situation.
int A::b = a;
You can set qualified-id but has no nested-name-specifier like this.
int A::b = ::a;
Solution 4 - C++
Because the name look up resolves the a
as A::a
. If you want to do this you will need to resolve the scope manually:
int A::b = ::a;
// ^ Global scope resolution