当从类方法调用命名空间中同名的函数时,重载解析失败

5
在下面的代码中,很明显函数定义myFn应该来自命名空间N并且有两个参数。但编译器无法编译它。这是编译器(g++ 8.3)的限制还是C++标准规定的?
    #include <bits/stdc++.h>

    using namespace std;

    namespace N
    {
      // Same name function exists in class A
      void myFn(int a, int b)
      {
        cout << a << ' ' << b << endl;
      }
    }

    using namespace N;
    class A {
      public:
        void myFn(int a)
        {
    #ifdef FINE
          // Explicitly specify where should myFn definition come from
          N::myFn(a, a);
    #else
          myFn(a, a);
    #endif
        }
    };

    int main()
    {
      A a;
      a.myFn(3);
      return 2;
    }

不要这样做:#include <bits/stdc++.h> - Daniel Langr
谢谢丹尼尔。我只是为了小型测试程序而这样做,生产质量的代码不应该使用它。 - rajpal gusain
1个回答

6

这是有意的。名称查找会停留在找到该名称的范围内。该机制确保您的代码行为相同,即使从包含范围添加或删除函数。

否则,更改 N 的成员可能会破坏封闭的类和命名空间。考虑一下潜在的灾难,如果添加一个与另一个类成员相比,重载决议更好的自由函数。 如果不被忽略,类的行为可能会因意外而改变!

这个例子应该说明了问题:

namespace ns {
  // void foo(int) { std::terminate(); }
  struct C {
      void foo(char) {}
      C() {
          foo(0);
      }
  };
}

根据当前的规则,取消注释foo不会有任何不良影响。但是如果名称查找确实考虑了它,因为0是一个int并且必须被转换char,构造C将会中止程序!这很极端并且很容易被察觉。但在一个真正的100M LOC程序中,行为不当的名称查找可能会导致更加阴险和更难以捕获的错误。


说到真正的生产质量代码,请阅读为什么不应该#include<bits/stdc++.h>?,尤其是联合阅读为什么“using namespace std”被认为是一种不好的做法? - StoryTeller - Unslander Monica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接