早期 C++ 编译器发行版并不支持 C++ 标准要求的函数重载。当前发行版修正了调用重载函数时出现的许多错误。具体来讲,当函数调用确实出现多义性时,编译器有时会选择某个函数;或者在函数调用实际上未产生多义性时,编译器会发出警告,指出此调用具有多义性。
采用某些解决方法来避免多义性消息已经没有必要了。也许您会看到以前未报告的新多义性错误。
导致函数调用多义性的一个主要原因在于仅重载内置类型的子集。
int f1(short); int f1(float); ... f1(1); // ambiguous, "1" is type int f1(1.0); // ambiguous, "1.0" is type double |
要解决此问题,要么根本不重载 f1,要么重载所有未提交的类型:int、unsigned int、long、unsigned long 和 double。(也许还有 long long、unsigned long long 以及 long double 类型)。
导致多义性的另一个主要原因在于:类中的类型转换函数,尤其是当您也重载了运算符或构造函数时。
class T { public: operator int(); T(int); T operator+(const T&); }; T t; 1 + t // ambiguous |
该操作有多义性是因为它可能被处理成:
T(1) + t // overloaded operator 1 + t.operator int() // built-in int addition |
可以提供重载运算符,也可以提供类型转换函数,但同时提供它们则会产生多义性。
实际上,类型转换函数自身也经常会导致多义性,而且往往在不应该进行转换时进行转换。如果您确实需要类型转换,最好使用命名的函数,而不是类型转换函数。例如,使用 int to_i t();,而不是 operator int();。
更改后,1 + t 操作就不再具有多义性了。它只能解释为 T(1) + t。如果您希望有其他的解释,必须写入 1 + t.to_int()。