在具有相同名称的全局函数中选择的类静态成员函数?

Ama*_*mar 10 c++ static-methods

怀疑起源于此


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();   
Run Code Online (Sandbox Code Playgroud)

最初我认为,当符号解析从最内部范围到最外部范围发生时,这就是为什么要调用x :: g().
但后来我密切注意到了这段代码

int Y::i = g();
Run Code Online (Sandbox Code Playgroud)

如何在没有名称范围的情况下访问X :: g()?
这个陈述所在的范围应该是全局的,而不是Y ::或X ::,所以符号解析应该给出函数g()的全局版本?

Naw*_*waz 11

注意:我认为我之前的回答是错误的.它不是Koenig Lookup,即依赖于Argument的名称查找(ADL).所以我删除了我(之前)的答案,因为我找到了标准中回答你问题的相关部分.

您的代码直接来自C++ 03标准的§9.4/ 2节.

静态成员可以直接在其类的范围内或在其类中派生的类(第10条)的范围内引用; 在这种情况下,静态成员被称为使用了qualified-id表达式,其中qualified-id的nested-name-specifier命名了引用静态成员的类作用域.

然后它给出了这个例子(你在问题中提到过)

[Example:

    int g();
    struct X {
        static int g();
    };
    struct Y : X {
        static int i;
    };
    int Y::i = g(); // equivalent to Y::g();

—end example]
Run Code Online (Sandbox Code Playgroud)

然后它在§9.4/ 3中说

如果 在成员的declarator-id之后的静态成员的定义中使用了unqualified-id(5.1),并且name lookup(3.4.1)发现unqualified-id引用静态成员,枚举器或嵌套类型在成员的类(或成员类的基类)中,unqualified-id被转换为qualified-id表达式,其中nested-name-specifier命名从中引用成员的类作用域.

由于这只发生在静态成员的定义中,这意味着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()
}
Run Code Online (Sandbox Code Playgroud)

请参阅此处的输出: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()
}
Run Code Online (Sandbox Code Playgroud)

请在此处查看完整演示:http://www.ideone.com/53hoW

  • 接受并完全理解.在你之前的回答中,我在想这里的论点在哪里.无论如何,感谢让我了解Koenig Lookup(我之前从未听说过),当然也回答了这个问题. (2认同)

Kir*_*rov 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找到了正确的解释,它在标准中并且似乎不是"依赖于参数的名称查找".但逻辑仍然是绝对相同的.