命名空间和范围可见性问题

时间:2011-07-12 13:23:11

标签: c++

我使用以下代码创建了一个头文件sampleheader.h

namespace sample_namespace
{
    int add(int n1,int n2)
    {
        return (n1 + n2);
    }
}

现在我的main.cpp文件是:

#include <iostream>
#include "sampleheader.h"
using namespace std;

int add(int n1, int n2)
{
  return (n1 + n2);
}

int main(void)
{
    using namespace sample_namespace;
    //cout<<add(5,7);
}

如果我对该行进行评论,则构建项目时不会发出警告。这是可以理解的,因为本地add()函数在全局范围内定义,add()函数在main范围内可见()。所以没有名称冲突发生。

但是,如果删除评论,我会收到以下错误:

"Ambiguous call to overloaded function"

首先,如上所述(如果我是对的),应该没有名称冲突。但是,如果有一个名称冲突,为什么只有在我调用该函数时它才被编译器通知。一旦名称冲突(如果有的话),就应该显示这种类型的错误。

感谢任何帮助。

5 个答案:

答案 0 :(得分:2)

嗯,你自己解释了。

如果范围内同时包含int add()int sample_namespace::add(),则调用不明确。声明add()可能意味着其中任何一个。

共存的功能没有冲突,因为一个是int add()而另一个是int sample_namespace::add()。这是名称空间的完整目的

编写使用它们的代码时,您必须清楚。如果你摆脱了using namespace指令并且总是编写显式代码,那么你就不会遇到问题:

#include <iostream>

namespace sample_namespace {
   int add(int n1, int n2) {
      return (n1 + n2);
   }
}

int add(int n1, int n2) {
   return (n1 + n2);
}

int main() {
    std::cout << sample_namespace::add(5,7);
}

(另外,在标题中定义非内联函数是A Bad Idea™。)

答案 1 :(得分:1)

“using namespace”不会隐藏其他实现。它在这种情况下的作用是使它模棱两可。

你有sample_namespace :: add和:: add,它们具有相同的签名。由于您没有明确说明要使用哪一个,因此编译器无法分辨。

声明这两个函数是合法且明确的(这就是为什么编译器只在你使用函数时会抱怨)。

答案 2 :(得分:0)

声明这两个函数合法的原因是因为你可以通过限定它们来明确地调用它们。这就是为什么只有在你打一个不合格的电话时才会收到错误的原因。到目前为止,甚至没有理论上的问题。

有意地,using namespace X;本身不应引入歧义错误。这将极大地破坏名称空间的目的。常见的using namespace std;引入了许多您自己合理定义的名称。

答案 3 :(得分:0)

你不能像这样影响符号,只能变量名称(这是大多数编译器的警告,即一个坏主意)。使用指令在任何意义上都不准确,我认为这是大多数人的假设。

using指令会将符号导入范围。例如,你可以这样做:

namespace foo {
  using namespace std;
}

foo::string val;

这种做法会导致一些非常烦人的编译器错误被追踪。您的简单示例清楚错误的位置。如果您尝试使用几十万行代码,那么您将不那么高兴。

我建议你不要养成依赖使用指令的习惯。如果必须,一次只做一种类型。

using std::string;

基本上,这会让你诚实。并且如果存在命名冲突,grep将需要30秒才能发现问题

如果您只是花几周时间在类型前键入std ::,您就会习惯它。我保证你认为你节省的时间被夸大了。

答案 4 :(得分:-1)

我认为这是因为编译器优化。当你的字符串被注释时 - 他看到,有一些功能,但你不使用它,所以他丢弃它。当他看到该函数有用时 - 他想插入函数调用,但无法选择你想要的函数。