It is due to "injected-name" — which means if foo
is a class-name, and the same name "foo" is also injected into the class-scope which is why your code works. It is 100% Standard-conformant.
Here is one interesting example which shows the benefits of this feature:
namespace N
{
//define a class here
struct A
{
void f() { std::cout << "N::A" << std::endl; }
};
}
namespace M
{
//define another class with same name!
struct A
{
void f() { std::cout << "M::A" << std::endl; }
};
struct B : N::A //NOTE : deriving from N::A
{
B()
{
A a;
a.f(); //what should it print?
}
};
}
What should a.f()
call? What is the type of a
? Is it M::A
or N::A
? The answer is, N::A
, not M::A
.
It is because of name-injection, N::A
is available inside the constructor of B
without qualification. It also hides M::A
, which remains outside the scope of B
. If you want to use M::A
, then you've to write M::A
(or better ::M::A
).
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…