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();
最初我认为,因为符号解析从最内部范围到最外部范围发生,这就是为什么要调用x :: g()。但是后来我仔细注意了代码
int Y::i = g();
我们如何在没有名称范围的情况下访问X :: g()?
这个语句所在的范围应该是全局的,而不是Y ::或X ::,所以符号解析应该给出函数g()的全局版本?
答案 0 :(得分:11)
注意:我认为我之前的回答是错误的。它不是Koenig Lookup,而是依赖于参数的名称查找(ADL)。所以我删除了我(之前)的答案,因为我找到了标准中回答你问题的相关部分。
您的代码直接来自C ++ 03标准的第9.4.2节。
可以参考静态成员 直接在其类或范围内 在派生类的范围内 (第10条)从其班级;在这 case,引用静态成员 好像是一个合格的id表达式 使用,使用嵌套名称说明符 命名类的qualified-id 静态成员的范围 引用。
然后给出了这个例子(你在问题中提到过)
[Example:
int g();
struct X {
static int g();
};
struct Y : X {
static int i;
};
int Y::i = g(); // equivalent to Y::g();
—end example]
然后在§9.4/ 3中说明
如果使用了nonqualified-id(5.1) 静态成员的定义 在会员的声明者身份之后, 和名称查找(3.4.1)发现 unqualified-id指静态 成员,枚举器或嵌套类型 成员的类(或基类) 成员的班级), unqualified-id转换为a qualified-id表达式中的 nested-name-specifier为该类命名 成员所在的范围 参考强>
由于在静态成员的定义中发生仅,这意味着{strong}初始化中仅调用Y::g()
,不在作业:
//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()
}
请参阅此处的输出:http://www.ideone.com/6KDMI
让我们考虑另一个例子:
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()
}
请参阅此处的完整演示:http://www.ideone.com/53hoW
答案 1 :(得分:9)
这是因为您使用int Y::i =...
,请注意Y::
。这就是原因,它实际上在g()
内寻找Y
,X::g()
,因为Y
派生X
。
添加:例如,如果您将int i = g();
放在int Y::i = g();
之后,则会产生以下结果:
In static member function X::g() In function g()
编辑:完全 - 依赖于参数的名称查找。我不记得在开始时这是怎么调用的。感谢Nawaz的回答(:
EDIT2 :好的,Nawaz找到了正确的解释,它在标准中并且似乎不是“依赖于参数的名称查找”。但逻辑仍然绝对相同。