c ++中的转换优先级

Mei*_*eir 4 c++

我有以下代码:

Some functions:

A::A(int i_a) {cout<<"int Ctor\n";}          //conversion constructor

void h(double d) {cout<<"double param\n";}   //f1
void h(A a) {cout<<"A param\n";}             //f2
Run Code Online (Sandbox Code Playgroud)

在主要功能:

h(1);
Run Code Online (Sandbox Code Playgroud)

h(1)调用的函数是f1.

我的问题是它为什么选择这样称呼它.1是一个int,因此需要隐式转换为double.它可以使用上面定义的转换构造函数轻松地将int转换为A.为什么我没有收到错误?什么是铸造的优先规则?


Nb我已经发布了我认为有必要回答这个问题的代码,但是下面我发布了整个代码:

 #include <iostream>
 using namespace std;
 class B;
 class A {
 public:
 explicit A(const B&) {cout<<"Ctor through B\n";}
 A() {cout<<"Default Ctor\n";}
 A(int i_a) {cout<<"int Ctor\n";}
 operator int() {cout<<"A => int\n"; return 2;}
 };
 class B {
 public:
 operator A() const {cout<<"B => A\n"; A a; return a;}
 };
 void h(double d) {cout<<"double param\n";}
 void h(A a) {cout<<"A param\n";}
 void f(const A& a)
 {
 cout<<"f function\n";
 //Without the const it will never try to convert
 }
 void main()
 {
 B b;
 cout <<"-----------------\n";
 f(b);
 cout <<"-----------------\n";
 h(1);
 }
Run Code Online (Sandbox Code Playgroud)

Fai*_*ali 14

当执行重载决策以从所有可行的重载中选择最佳候选时 - 编译器对每个候选的每个参数的所有转换序列进行排序.对于要获胜的函数(被选为最佳候选者),其每个参数的转换等级必须优于或等于该参数的每个其他函数的转换等级,并且至少一个转换等级必须优于所有其他转换等级.函数的转换排名为某个参数.

用户定义的转换(使用构造函数或强制转换运算符)具有最差的排名之一(只有省略号的排名更差).积分浮动转换具有更好的排名(参见下面的排名列表).

因此,编译器更喜欢转换int - > double(使用标准转换)而不是转换int - > A(使用用户定义的转换),因此它选择f1.

编辑:虽然"重载分辨率"在后台工作,但大部分时间完全符合您的预期(即大多数程序员不需要深入研究技术细节) - 如果您确实想要深入(但要注意一些过载分辨率的较暗角落被认为是编译器编写者在C++编译器中完全正确的最棘手的方面之一)参考优秀的 C++模板:David Vandevoorde和Nicolai M. Josuttis提供的完整指南,附录B,我读过的关于重载决议背后机械的最佳介绍之一.

以下是B.2的摘录:

重载分辨率通过比较调用的每个参数如何匹配候选的相应参数来对可行的候选函数进行排序.对于一个被认为比另一个更好的候选者,更好的候选者不能使其任何参数与另一个候选者中的相应参数相比更差....

鉴于第一个原则,我们留下指定给定参数与可行候选者的相应参数的匹配程度.作为第一个近似值,我们可以按如下方式对可能的匹配进行排名(从最佳到最差):

完美的一对.该参数具有表达式的类型,或者它具有一个类型,该类型是对表达式类型的引用(可能添加了const和/或volatile限定符).

匹配微小的调整.例如,这包括将数组变量衰减到指向其第一个元素的指针,或者将类型为int**的参数的const添加到类型为int const*const*的参数中.

与促销相匹配.提升是一种隐式转换,包括将小整数类型(例如bool,char,short,有时是枚举)转换为int,unsigned int,long或unsigned long,以及将float转换为double.

仅与标准转化匹配.这包括任何类型的标准转换(例如int到float),但不包括对转换运算符或转换构造函数的隐式调用.

与用户定义的转化匹配.这允许任何类型的隐式转换.

与省略号匹配.省略号参数几乎可以匹配任何类型(但非POD类类型会导致未定义的行为).

但这只是一个开始 - 如果你很感兴趣 - 我恳请你阅读这本书然后标准的相关部分:)