为什么类成员函数具有相同名称的阴影自由函数?

时间:2012-07-27 21:42:30

标签: c++ overloading member-functions name-lookup name-hiding

It recently came to my attention该成员在课堂内使用相同名称的完全 shadow 免费函数。完全我的意思是,每个具有相同名称的自由函数根本不考虑重载解析。我可以理解为什么这样做会像这样:

void f();

struct S
{
    void f();

    void g()
    {
        f(); // calls S::f instead of ::f
    }
};

其中函数具有相同的签名,其唯一自然的变量作用域以相同的方式工作。但是为什么要禁止在自由函数具有不同签名的无意义调用:

void f();

struct S
{
    void f(int x);

    void g()
    {
        f(); // fails to compile attempting to call S::f, which has wrong signature
    }
};

我不是问如何从类中调用 shadowed 自由函数。我想知道的是这种设计背后的基本原理。

3 个答案:

答案 0 :(得分:7)

对于非限定名称查找,一次只考虑一个范围,如果该范围内的搜索未产生任何结果,则搜索下一个更高范围。在您的情况下,只搜索S的范围。

  

但是为什么禁止自由函数具有不同签名的无意义调用:

问题是名称查找除了名称​​标识符之外没有任何其他内容。你完全忘记了你想要调用一个函数,它只是看到一个标识符。如果您只使用auto x = f;,则会发生相同的名称查找,如果您这样想,那么您只需要非常有限的搜索范围就有很好的理由。任何其他东西都会让用户感到惊讶。

答案 1 :(得分:3)

有一个特殊的,非常令人惊讶的规则(但它不适用于您的示例)声明一旦通过名称查找找到类成员名称,就不会搜索任何命名空间范围:

#include <string>

struct C {
    std::string s;

    explicit C (std::string);

    void swap (C& rhs) {
        swap (s, rhs.s); // error: swap is C::swap
    }   
};

void swap (C& lhs, C& rhs) {
    swap (lhs.s, rhs.s); // std::swap(string,string)
}

IMO,这很疯狂。

  

但是为什么禁止自由函数具有不同签名的无意义调用:

在重载分辨率之前发生名称查找:

  • 如果查找不明确,则不会重载分辨率。
  • 如果通过名称查找找不到可行的功能,则不会尝试其他轮次查找。

规则足够复杂,在重载和名称查找之间没有“反馈”。我建议简化(比如删除成员隐藏命名空间范围名称规则,并删除模糊名称查找)而不是复杂化。

答案 2 :(得分:2)

我无法提供一个权威的答案(也许有人记得Design and Evolution of C++的引用或者当时已经在委员会中的引用),但我的第一个猜测是在你展示的情况下完全失败。很容易忘记在某个时间范围内有多少东西。此外,重载解析可能非常复杂,可能存在默认参数和转换。所以我宁愿在这种情况下拥有最有限的范围,以确保始终确切地调用它。