Doubt originated from here
int g() {
cout << "In function g()" << endl;
return 0;
}
class X {
public:
static int g() {
cout << "In static member function X::g()" << endl;
return 1;
}
};
class Y: public X {
public:
static int i;
};
int Y::i = g();
initially I though that as symbol resolution happens from inner most scope to outer most scope, that is why x::g() would be called.
but then I closely noticed the code
int Y::i = g();
how are we able to access X::g() without namescope?
And scope in which this statement lies should be global, not Y:: or X:: , so symbol resolution should give global version of the function g()?
Note: I think my earlier answer was wrong. Its not Koenig Lookup i.e Argument-dependent name lookup (ADL). So I deleted my (earlier) answer since I found the relevant section from the Standard which answers your question.
Your code is directly from the section §9.4/2 of the C++03 Standard.
A static member may be referred to directly in the scope of its class or in the scope of a class derived (clause 10) from its class; in this case, the static member is referred to as if a qualified-id expression was used, with the nested-name-specifier of the qualified-id naming the class scope from which the static member is referenced.
It then gives this example (which you've asked in the question)
[Example:
int g();
struct X {
static int g();
};
struct Y : X {
static int i;
};
int Y::i = g(); // equivalent to Y::g();
—end example]
It then says that in §9.4/3
If an unqualified-id (5.1) is used in the definition of a static member following the member’s declarator-id, and name lookup (3.4.1) 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.
Since that happens only in the definition of the static member, that means Y::g()
is called ONLY in the initialization, not in assignment:
//definition-cum-initialization
int Y::i = g(); // equivalent to Y::g();
int main()
{
//assignment
Y::i = g(); // does not equivalent to Y::g(); it calls global g()
}
See the output here : http://www.ideone.com/6KDMI
Lets consider another example:
struct B{};
B f();
namespace NS
{
struct A { static B b;};
B f();
}
//Definition cum Initialization
B NS::A::b = f(); //calls NS::f()
B b = f(); //calls global f()
int main()
{
//Assignment
NS::A::b = f(); //calls global f()
b = f(); //calls global f()
}
See the complete demo here : http://www.ideone.com/53hoW
This is because you use int Y::i =...
, note the Y::
. That's why, it actually looks for g()
inside Y
, which is X::g()
, because Y
derives X
.
Addition: For example, if you put int i = g();
after int Y::i = g();
, there result would be:
In static member function X::g() In function g()
EDIT: exactly - Argument-dependent name lookup. I couldn't remember how this is called at the beginning. Thanks Nawaz's answer (:
EDIT2: OK, Nawaz found the correct explanation, it's in the standard and it seems not to be "Argument-dependent name lookup". But the logic is still absolutely the same.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With