函数重载中的规则



看看这个代码(例如):

#include <iostream>
void print(unsigned int value);
void print(float value);
int main() {
print('a');
print(0);
print(3.14159);
return 0;
}

我收到下一个错误:

"打印(字符)"是模棱两可的

这里真正的问题是什么?我知道不止一个函数适用于来自主函数(打印函数)的任何调用。但是function overloading中的真正规则是什么(我怎么知道什么适合什么,哪些类型之间存在强制转换等)

我如何知道有多个函数适合调用? (更多示例:如何理解这两个函数是否适合调用并不明显)

#include <iostream>
void print(unsigned int value);
void print(int value);
int main() {
print(2.5);
}

当您使用函数重载时,编译器在后台执行大量工作来执行函数重载解析。细节在这里列出很好,但是我可以提供一些可能有用的链接,并尝试描述一些更重要的部分。

  • CPP 首选项:过载分辨率
  • ACCU:过载分辨率
  • 学习 CPP:函数重载

有 3 种可能的结果:

  • 找到匹配项。调用解析为特定重载
  • 未找到匹配项。参数不能与任何重载匹配
  • 发现不明确的匹配项。参数匹配多个重载

编译器将执行的操作的基本顺序是这样的:

  • 根据参数列表查找完全匹配项
  • 尝试通过促销找到匹配项
  • 尝试通过标准转换找到匹配项
  • 尝试通过用户定义的转换找到匹配项

那么如何确定呼叫是否模棱两可呢?

由于每个重载都必须具有唯一的参数,并且由于所有标准转换和所有用户定义的转换都被视为相等的事实;如果函数调用通过标准或用户定义的转换匹配多个有效的声明定义候选,则结果将是模棱两可的。


从您的示例中:

void print( unsigned int value );
void print( float value );
print( 'a' );
print( 0 );
print( 3.14159 ); 

print( 'a' );C++的情况下找不到完全匹配。它将首先尝试将'a'提升为int,但是没有声明定义的print(int)函数。然后它将尝试使用标准转换,它可以将'a'转换为unsigned intfloating point值。由于所有标准转换都被认为是平等的,这会导致歧义。


若要解决这种多义性,可以简单地declare-define所需的print( type );版本,也可以将类型显式转换为提供的重载参数类型之一。

由于缺少print版本而获得的错误:

print('a'); // calling print(int)
print(0);   // calling print(int) 
print(3.14159); // calling print(double) not float

如您所见,print(int)print(double)也丢失了print(char)丢失了,您会得到这些错误。例如,当print(char)未提供时,编译器将搜索print(int)因此它将传入的值转换为整数。

要解决这个问题,您可以添加重载print的版本,或者显式转换传入的值:

1-超载打印:

void print(int value){ cout << "int: " <<  value << endl;}
void print(unsigned int value){ cout << "ui: " <<  value << endl;}
void print(float value){cout << "float: " << value << endl;}
void print(char c){ cout << "Char: " << c << endl;}
void print(double value){cout << "double: " << value << endl;}

2- 铸造:

print((unsigned int)'a'); // or (float)
print((unsigned int)0);  // or (float)
print(3.14159f); // or (float)3.14159 or (unsigned int)3.14159
  • 请记住,print(3.14159);是对print(double);的呼吁,不要float为浮点数这样做:print(3.14159f);

最新更新