我不知道重载解析在这里是如何工作的!对于第一个片段,它解析为 OVERLOAD A,但对于第二个片段,它会引发错误“不明确的调用”。
代码1
#include <iostream>
using namespace std;
void doThings_A(int ,int ,double){ cout<<"first fxn"<<endl;} //OVERLOAD A
void doThings_A(int ,double,double){ cout<<"second fxn"<<endl;} //OVERLOAD B
int main() {
// Write C code here
doThings_A(4,5,6);
return 0;
}
代码 1 的输出:第一个 fxn
代码2
#include <iostream>
using namespace std;
void doThings_A(double ,int ,int){ cout<<"first fxn"<<endl;}
void doThings_A(int ,double,double){ cout<<"second fxn"<<endl;}
int main() {
// Write C code here
doThings_A(4,5,6);
return 0;
}
代码 2 的输出:
error: call of overloaded 'doThings_A(int, int, int)' is ambiguous
8 | doThings_A(4,5,6);
| ~~~~~~~~~~^~~~~~~
/tmp/sI0f5j5PL7.cpp:4:6: note: candidate: 'void doThings_A(double, int, int)'
4 | void doThings_A(double ,int ,int){ cout<<"first fxn"<<endl;}
| ^~~~~~~~~~
/tmp/sI0f5j5PL7.cpp:5:6: note: candidate: 'void doThings_A(int, double, double)'
5 | void doThings_A(int ,double,double){ cout<<"second fxn"<<endl;}
C++ 在这方面的设计方式(无论是选择重载还是模板特化、比较
concept
强度等)的一般原则是它不 为不同的替代方案分配“分数”(基于参数的数量)如果我们谈论函数重载或其他任何东西,则需要隐式转换。
相反,要使 A 比 B 更好,A 必须在所比较的每个单独方面不更差,并且至少在一个方面更好。
对于函数重载,比较的“方面”是每个单独的参数是否需要隐式转换:
在第一个片段中,两个重载对于参数 1 和 3 来说是等效的(即,没有一个比另一个更差),但是第一个重载相对于参数 2 更好。因此,第一个重载总体上更好。
在第二个片段中,第一个重载相对于参数 2 和 3 更好,但第二个重载相对于参数 1 更好,因此存在歧义。
当然,还有更多细微差别,但一般原则仍然成立:
这里的决定因素是(过载分辨率 - 最佳可行功能):
如果 F1 所有参数的隐式转换不比 F2 所有参数的隐式转换差,则确定 F1 是比 F2 更好的函数,并且
- F1 中至少有一个参数的隐式转换优于 F2 中该参数的相应隐式转换
让我们看看签名:
void doThings_A(int ,int ,double) // 1
void doThings_A(int ,double,double) // 2
当使用三个
int
调用时,第一个和第三个参数对于 1 和 2 都同样有效 - 分别是匹配和浮点提升。
但在第二个参数中,1 是匹配,而 2 需要浮点提升。这意味着对于每个参数,1 都等于或优于 2,因此选择 1。
但是,在第二个示例中,我们有:
void doThings_A(double ,int ,int) // 3
void doThings_A(int ,double,double) // 4
这里 3 更好地匹配第二个和第三个参数,而 4 更好地匹配第一个参数。这意味着没有明显更好的候选者,因此决议失败。
在这两种情况下,两个重载
doThings_A
对于调用doThings_A(4,5,6)
来说都是可行的函数,但在第一种情况下,一个是另一个“更好的函数”。
如果
F1
的所有参数的隐式转换不比F2
的所有参数的隐式转换差,则被确定为比F1
更好的函数,并且F2
- 该参数的相应隐式转换
中至少有一个参数的隐式转换优于F1
F2
在这两种情况下,最差的隐式转换(
int
到double
)是相同的,因此必须考虑子句1.
。让我们逐个比较案例:
CASE 1
| arg1 | arg2 | arg3 |
CALL | int | int | int |
F1 | int (exact match) | int (exact match) | double (conversion) |
F2 | int (exact match) | double (conversion) | double (conversion) |
WINS | tie | F1 | tie |
至少有一个参数 (
arg2
) 的隐式转换更好,F1
获胜并且是最佳可行函数。
CASE 2
| arg1 | arg2 | arg3 |
CALL | int | int | int |
F1 | double (conversion) | double (conversion) | int (exact match) |
F2 | int (exact match) | double (conversion) | double (conversion) |
WINS | F2 | tie | F1 |
按照同样的规则,
F1
是比F2
(arg3
)更好的可行函数,并且F2
是比F1
(arg1
)更好的可行函数。这导致两个函数的排名相等,因此出现不明确的调用错误。