当我使用"using namespace std;"和"bits/stdc++.h"时,为什么在这段代码中会出现错误?

3

实际上这段代码在“DEV C++”中运行良好,但当我将其放入我的“Hacker-Rank”面板时,它会出现“reference to function is ambiguous”的错误,尽管所有在线编译器都会出错...

我认为这里函数重载并没有干扰任何地方,因为这种错误大多发生在函数重载中。

#include <bits/stdc++.h>
#include <cstdio>
#include<iostream>

using namespace std;


int function(int n);

int main()
{
    int n;
    cin >> n;
    cin.ignore(numeric_limits<streamsize>::max(), '\n');    

    if(n<=0){
        return(0);
    }
    else{
        function(n);
    }

}
int function(int n)
{
    if (n<=9)
    {
        cout<<"experiment";
    }
    
    else{
        cout<<"Greater than 9";
    }
    return 0;
}

使用clang时出现的错误为:

<source>:20:9: error: reference to 'function' is ambiguous
        function(n);
        ^
<source>:8:5: note: candidate found by name lookup is 'function'
int function(int n);
    ^
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/11.0.0/../../../../include/c++/11.0.0/bits/std_function.h:111:11: note: candidate found by name lookup is 'std::function'
    class function;
          ^
// ... and more ....

1
不要使用 using namespace std; - molbdnilo
1
如果您已经包含了 <bits/stdc++.h>,那么为什么还要包含其他头文件呢? - Arsenic
2
请勿解释错误信息,将其原样包含在问题中。该消息具有有用的信息,不要忽略它。 - 463035818_is_not_a_number
1
@Yunnosch,我还添加了错误消息,不确定这如何干扰“尽管所有在线编译器都会产生错误......”,这应该是一个打字错误吧(“没有*给出错误”?!?)。 - 463035818_is_not_a_number
@largest_prime_is_463035818 我也是这样认为。如果有“不”字的话,这篇文章会更有意义。fly_high,请澄清一下。 - Yunnosch
显示剩余7条评论
3个回答

5

首先,这段 else 代码块的作用是

else{
    function(n);
}

没有返回值。

虽然允许,但会使程序的读者困惑,因为如果if子语句中有显式的return语句,则期望else子语句中也应该有类似的return语句。

由于使用指令,全局命名空间中声明的名称function与标准名称std :: function冲突。

using namespace std;

编写代码

else{
    return ::function(n);
}

1
这是一个很好的反模式例子,会带来麻烦。我很想将许多提到这里的问题标记为重复关闭。 - Yunnosch
你讲得很简洁明了。我在许多代码中都遇到了这个错误,但现在我只需更改函数名称,就可以完美地解决问题了。太好了,感谢你! - Just_chill
@fly_high 无论如何,最好使用合格的名称。 - Vlad from Moscow

2
问题是由于#include <bits/stdc++.h>和指令using namespace std组合使用引起的。 <bits/stdc++.h>包含了与C++标准库相关的大多数(根据您所使用的编译器版本的年龄而定,可能是全部)头文件。 <bits/stdc++.h>中包含的一个头文件(自C++11以来)是<functional>,它声明了一个模板类std :: functionstd :: function有一个模板构造函数,可以接受任何类型的单个参数。
在您的main()中,任何被声明(对编译器可见)且命名为function的内容都有可能被语句function(n)使用。指令using namespace std告诉编译器要将std内的名称视为候选项。根据语言规则,您声明的function()std :: function都是名称function的等效匹配项。
真正的修复程序有两个部分。首先,避免使用像<bits/stdc++.h>这样的头文件,而只包括实际上需要的标准头文件。
第二部分是避免过度使用指令using namespace std,甚至不使用它。这可能会导致标准头文件中的名称(类型、函数、变量等)与代码中的名称意外匹配。
如果您进行搜索,您将找到大量解释为什么要避免使用<bits/stdc++.h>和避免使用using namespace std(或其他using指令)。这两者都有其用途,但都会引入难以避免的陷阱(例如您所经历的情况)。

1

Vlad已经证明,通过避免使用using namespace std;可以解决您的问题。这是一个好答案。

有趣的是,即使没有Vlad提出的改进,您也可以通过不使用反模式#include <bits/stdc++.h>来解决问题。

#include <limits>
#include <cstdio>
#include<iostream>


using namespace std;

int function(int n);

int main()
{
    int n;
    cin >> n;
    cin.ignore(numeric_limits<streamsize>::max(), '\n');    

    if(n<=0){
        return(0);
    }
    else{
        function(n);
    }

}
int function(int n)
{
    if (n<=9)
    {
        cout<<"experiment";
    }
    
    else{
        cout<<"Greater than 9";
    }
    return 0;
}

我为什么敢称之为“反模式”的更多信息在这里:
为什么不应该#include <bits/stdc++.h>?


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