c ++中的转换优先级

时间:2009-07-07 14:35:49

标签: 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

在主要功能中:

h(1);

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

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


N.b。我已经在上面发布了我认为有必要回答这个问题的代码, 但是下面我发布了整个代码:

 #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);
 }

2 个答案:

答案 0 :(得分:14)

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

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

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

编辑:虽然“重载分辨率”在后台工作,但大部分时间完全符合您的预期(即大多数程序员不需要深入研究技术细节) - 如果您确实想要更深入(但是警告说,重载解析的一些较暗的角落被认为是编译器编写者在C ++编译器中完全正确的最棘手的方面之一)参考优秀的 C++ Templates: The Complete Guide by David Vandevoorde and Nicolai M. Josuttis,它在附录B中提供了一个我读过的关于重载决议背后的机器的最佳介绍。

以下是B.2的摘录:

  

重载分辨率排名可行   候选函数通过比较如何   呼叫的每个参数都匹配   相应的参数   候选人。对于一个候选人   被认为比另一个更好,   更好的候选人不能拥有任何   它的参数比较差   相应的参数   其他候选人。   ...

     

鉴于这第一个原则,我们是   留下指定给定的程度   参数匹配相应的   可行候选人的参数。作为一个   我们可以对第一近似值进行排序   可能的匹配如下(从最佳   最坏的):

     

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

     

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

     

与促销相匹配。促销是一个   那种隐式转换   包括转换小   整数类型(如bool,char,   简短,有时候是枚举)   int,unsigned int,long或unsigned   很长,并且将float转换为   双

     

仅与标准转化匹配。   这包括任何标准   转换(例如int到float)但是   排除对a的隐式调用   转换运算符或转换   构造

     

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

     

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

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

答案 1 :(得分:0)

加入标准(N4687)

  

2

     

比较隐式转换序列的基本形式时(如   在16.3.3.1)中定义

     

- (2.1)标准转换序列   (16.3.3.1.1)是比用户定义的更好的转换序列   转换序列或省略号转换序列,

     

- (2.2)a   用户定义的转换序列(16.3.3.1.2)是一种更好的转换   序列而不是省略号转换序列(16.3.3.1.3)。