传递NULL作为参数时,函数重载如何工作?

Gal*_*axy 0 c++ overloading overload-resolution c++11

我知道NULL是#defined为0.它似乎是一个int转换为指针类型的常量.那么当有两个重载函数时会发生什么:一个采用指针类型,另一个采用int类型.这是如何工作的nullptr

#include <iostream>
using namespace std;

void callMe(int* p)
{
    cout << "Function 1 called" << endl;
}

void callMe(int i)
{
    cout << "Function 2 called" << endl;
}

int main()
{
    callMe(nullptr);
    callMe(NULL);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我知道callMe(nullptr)肯定会调用第一个函数.但是哪个函数会被调用callMe(NULL)?我在我的电脑上编译了这段代码.只有一个警告.

g++ -std=c++11 nullptr_type.cpp
nullptr_type.cpp: In function 'int main()':
nullptr_type.cpp:44:14: warning: passing NULL to non-pointer argument 1 of 'void callMe(int)' [-Wconversion-null]
   callMe(NULL);
          ^
Run Code Online (Sandbox Code Playgroud)

我的代码编译没有任何问题,当我运行它时,我看到callMe(NULL)称为函数2. Visual Studio也编译代码,它调用函数2.

但是,当我尝试在在线GeeksForGeeks IDE上编译我的代码时,我遇到了一些编译器错误.

https://ide.geeksforgeeks.org/UsLgXRgpAe

我想知道为什么会出现这些错误.

prog.cpp: In function 'int main()':
prog.cpp:17:13: error: call of overloaded 'callMe(NULL)' is ambiguous
  callMe(NULL);
             ^
prog.cpp:4:6: note: candidate: void callMe(int*)
 void callMe(int* p)
      ^
prog.cpp:9:6: note: candidate: void callMe(int)
 void callMe(int i)
      ^
Run Code Online (Sandbox Code Playgroud)

在线Ideone IDE和在线TutorialsPoint CodingGround IDE生成相同的错误.这实际上是否定义了行为?

这种情况怎么样?这里会调用哪些函数?

#include <iostream>
using namespace std;

void callMe(int* p)
{
    cout << "Function 1 called" << endl;
}

void callMe(char* cp)
{
    cout << "Function 2 called" << endl;
}

void callMe(nullptr_t np)
{
    cout << "Function 3 called" << endl;
}

void callMe(int i)
{
    cout << "Function 4 called" << endl;
}

int main()
{
    callMe(nullptr);
    callMe(NULL);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

一个更普遍的问题,但我认为这就是它的全部内容:当重载函数时,您如何知道哪些函数调用是不明确的?我想知道在这个问题的答案中,有多个函数是争论的竞争对手.如果只有一个函数,那么这个参数会没有错误.但是当几个函数似乎同样可能采取这种论点时会发生什么?

链接的问题是关于NULL在C中使用.我的问题是关于C++.C编程语言没有运算符重载,因此我提到的大多数问题只是C++特定的东西.

================================================== =========================

这是一个相关的问题,详细解释了问题及其解决方案.那一个有很多有用的答案.

使用nullptr有什么好处?

M.M*_*M.M 5

我知道NULL是#defined为0.

一般来说,这不是真的,可以定义为nullptr.它可能是0L.还有其他可能性,例如我尝试的gcc版本定义它__null显然是gcc的空指针常量扩展.

重载函数时,如何知道哪些函数调用不明确?

通过阅读C标准的过载分辨率部分.这是其中最复杂的部分之一.简而言之,排序不同的转换序列,并且一些转换序列具有比其他转换序列更高的等级.有一个关于cppreference的介绍.

  • callMe(0)解析为(int)因为完全匹配优先于转换.(调用(int *)版本需要整数到指针转换)
  • callMe(nullptr)解析(int *)因为从甚至没有任何转换nullptrint
  • callMe(NULL)取决于如何定义NULL.如果0nullptr,见上文.如果0L那么它是不明确的,因为需要转换以匹配大小写和整数转换具有与整数到指针转换相同的等级.等等.