重载决议:这怎么不模糊?

时间:2014-12-05 13:07:36

标签: c++ language-lawyer overload-resolution

假设我们有这个代码,从一个单独的问题复制:

namespace x 
{
    void f()
    {
    }

    class C 
    {
        void f() 
        {
            using x::f;
            f();         // <==
        }
    };
}

指定行上的名称f明确指代x::f(至少根据gcc和clang)。在这种情况下,为什么x::f优先于x::C::f?两个名字都可见,这不应该是模棱两可的吗?

3 个答案:

答案 0 :(得分:10)

因为using声明会将x::f带入f的范围,该范围比C的范围窄。非限定查找会考虑本地块范围,找到匹配项,并在考虑更广泛的类范围之前停止。由于没有函数参数,因此没有依赖于参数的查找,因此不会考虑其他范围。

答案 1 :(得分:7)

@ MikeSeymour的回答是现场的;这里是相关的标准引用(C ++ 11,强调我的):

13.3.1.1.1 / 3:

  

在非限定函数调用中,该名称不受->.运算符限定,并且具有更通用的形式    primary-expression。在正常规则之后的函数调用的上下文中查找名称   用于函数调用中的名称查找(3.4)。该查找找到的函数声明构成了一组   候选职能。 由于名称查找规则,候选函数集完全由(1)组成   非成员函数或(2)完全属于某个类T的成员函数。 ......

3.4.1 / 1:

  

在3.4.1中列出的所有情况下,范围将按照每个中列出的顺序搜索声明   各自的类别;一旦找到名称的声明,名称查找就会结束。如果没有声明   发现,该计划格式不正确。

3.4.1 / 8

  

在函数的 declarator-id 之后定义类X的成员函数(9.3)的名称   ......应在其中一个中宣布   以下方式:

     
      
  • 在使用它之前或在封闭块(6.3)或
  • 中使用之前   
  • 应该是类X的成员,或者是X(10.2)的基类成员,或者
  •   
  • ...
  •   

从3.4.1 / 8开始,我们看到名称f的声明(例如声明using x::f;)在其使用的块中的列出早于f作为班级C的成员。根据3.4.1 / 1,选择较早的一个,因此整个查找解析为x::f声明引入的using

答案 2 :(得分:1)

我认为C ++标准中的这些引用是相关的:

来自C ++标准(7.3.3使用声明)

  

13由于使用声明是声明,因此受到限制   同一声明区域中的同名声明(3.3)   也适用于使用声明。

和(3.3.7班级范围)

  

4)在成员函数中声明的名称隐藏了声明   范围扩展到或超过成员结尾的同名   功能的类。