我有一个单身人士:
struct foo {
static foo& instance() {
static foo f;
return f;
}
};
Run Code Online (Sandbox Code Playgroud)
在重新安排一些代码时,我最终得到了"错误"这句话:
foo::foo::instance()
Run Code Online (Sandbox Code Playgroud)
但是我的编译器认为这是正确的(gcc 4.7).事实上,甚至foo::foo::foo::instance()编译.为什么?
Naw*_*waz 45
这是由于"注入名称" - 这意味着if foo是一个类名,并且同样名称"foo"也被注入到类范围中,这就是代码工作的原因.它符合标准100%.
这是一个有趣的例子,展示了这个功能的好处:
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?
}
};
}
Run Code Online (Sandbox Code Playgroud)
该怎么a.f()称呼?是什么类型的a?难道M::A还是N::A?答案是N::A,不是M::A.
这是因为名称注入,N::A在B没有资格的构造函数内可用.它也隐藏 M::A,但仍然不在范围内B.如果你想使用M::A,那么你要写M::A(或更好::M::A).
Ant*_*vin 21
因为[class]/2:
一个类名被插入在其中后立即宣布的范围类的名字能够被看见.的类名也被插入到类本身的范围; 这被称为注入类名.
所以foo::foo是一个注入的类名,表示foo本身.
实际上它有点复杂:根据[class.qual]/2,foo::foo单独表示一个构造函数foo.为了表示一个类,它应该在struct(使其成为详细类型说明符)之后,或者后面跟着::(使它成为嵌套名称说明符 - 这是你的情况),或者是一个基本说明符(对于例子struct bar : foo::foo {};).
Lor*_*ins 11
如其他答案中所述,原因是名称注入.对我来说,主要用例如下
struct B1 { void f(){} };
struct B2 { void f(){} };
struct D : B1, B2 { }
int main() {
D obj;
obj.f();
}
Run Code Online (Sandbox Code Playgroud)
在main调用f是模糊的,不会编译.具体的方式是合格的呼叫,即
obj.B1::f();
Run Code Online (Sandbox Code Playgroud)