简体   繁体   English

C++中的转换优先级

[英]conversion precedence in c++

I have the following code:我有以下代码:

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

In the main function:在主函数中:

h(1);

The function that h(1) calls is f1. h(1) 调用的函数是 f1。

My question is why does it choose to call that.我的问题是它为什么选择这样称呼。 1 is an int and therefore requires implicit conversion to double. 1 是一个 int,因此需要隐式转换为 double。 It could just as easily convert the int into an A using the conversion constructor defined above.它可以使用上面定义的转换构造函数轻松地将 int 转换为 A。 Why don't I get an error?为什么我没有收到错误消息? What are the precedence rules with casting?铸造的优先规则是什么?


Nb I've posted above the code that I think will be necessary to answer the question, but below I'm posting the entire code:注意,我已经在我认为回答问题所必需的代码上方发布了代码,但在下面我发布了整个代码:

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

When overload resolution is performed to select the best candidate out of all viable overloads - the compiler ranks all the conversion sequences for each argument for each candidate.当执行重载决议以从所有可行重载中选择最佳候选时 - 编译器对每个候选的每个参数的所有转换序列进行排序。 For a function to win (be selected as the best candidate), its conversion ranks for each argument have to be better than or equal to every other function's conversion ranks for that argument AND at least one conversion rank has to be better than all the other function's conversion ranks for a certain argument.要使某个函数获胜(被选为最佳候选者),其每个参数的转换等级必须优于或等于该参数的每个其他函数的转换等级,并且至少一个转换等级必须优于所有其他函数函数对某个参数的转换排名。

The user defined conversion (which uses either a constructor or a cast operator) has one of the worst possible ranks (only the ellipsis has a worse rank).用户定义的转换(使用构造函数或强制转换运算符)具有可能的最差等级之一(只有省略号具有更差的等级)。 The integral-floating conversion has a better rank (see below for a list of the rankings).整数-浮点转换具有更好的排名(请参阅下面的排名列表)。

Thus, the compiler prefers converting an int -> double (using a standard conversion) than converting an int -> A (using a user defined conversion), and therefore it selects f1.因此,编译器更喜欢转换 int -> double(使用标准转换)而不是转换 int -> A(使用用户定义的转换),因此它选择 f1。

Edit: Although "Overload resolution" works in the background and most of the time does exactly what you would expect (ie most programmers won't need to delve into the technicalities) - if you do want to go deeper (but be warned that some of the darker corners of overload resolution are considered to be one of the trickiest aspects for compiler writers to get exactly right in a C++ compiler) refer to the excellent C++ Templates: The Complete Guide by David Vandevoorde and Nicolai M. Josuttis which provides, in appendix B, one of the best introductions to the machinery behind overload resolution that I have read.编辑:虽然“重载解决方案”在后台工作,并且大部分时间完全符合您的预期(即大多数程序员不需要深入研究技术细节)-如果您确实想更深入(但请注意,有些重载决议的阴暗角落被认为是编译器作者在 C++ 编译器中完全正确的最棘手的方面之一)请参阅优秀的C++ 模板:David Vandevoorde 和 Nicolai M. Josuttis 的完整指南,其中提供了附录 B,我读过的关于过载解决机制的最佳介绍之一。

Here is an excerpt from B.2:以下是 B.2 的摘录:

Overload resolution ranks the viable candidate functions by comparing how each argument of the call matches the corresponding parameter of the candidates.重载解析通过比较调用的每个参数如何匹配候选函数的相应参数来对可行的候选函数进行排名。 For one candidate to be considered better than another, the better candidate cannot have any of its parameters be a worse match than the corresponding parameter in the other candidate.对于一个被认为比另一个更好的候选者,更好的候选者的任何参数都不能比另一个候选者中的相应参数更差。 ... ...

Given this first principle, we are left with specifying how well a given argument matches the corresponding parameter of a viable candidate.鉴于第一个原则,我们剩下来指定给定参数与可行候选者的相应参数的匹配程度。 As a first approximation we can rank the possible matches as follows (from best to worst):作为第一个近似值,我们可以将可能的匹配排序如下(从最好到最差):

Perfect match.完美搭配。 The parameter has the type of the expression, or it has a type that is a reference to the type of the expression (possibly with added const and/or volatile qualifiers).参数具有表达式的类型,或者它的类型是对表达式类型的引用(可能添加了 const 和/或 volatile 限定符)。

Match with minor adjustments.配合微调。 This includes, for example, the decay of an array variable to a pointer to its first element, or the addition of const to match an argument of type int** to a parameter of type int const* const*.例如,这包括数组变量衰减到指向其第一个元素的指针,或添加 const 以将 int** 类型的参数与 int const* const* 类型的参数匹配。

Match with promotion.与促销相匹配。 Promotion is a kind of implicit conversion that includes the conversion of small integral types (such as bool, char, short, and sometimes enumerations) to int, unsigned int, long or unsigned long, and the conversion of float to double.提升是一种隐式转换,包括小整数类型(如 bool、char、short,有时还有枚举)到 int、unsigned int、long 或 unsigned long 的转换,以及 float 到 double 的转换。

Match with standard conversions only.仅与标准转换匹配。 This includes any sort of standard conversion (such as int to float) but excludes the implicit call to a conversion operator or a converting constructor.这包括任何类型的标准转换(例如 int 到 float),但不包括对转换运算符或转换构造函数的隐式调用。

Match with user-defined conversions.与用户定义的转换匹配。 This allows any kind of implicit conversion.这允许任何类型的隐式转换。

Match with ellipsis.与省略号匹配。 An ellipsis parameter can match almost any type (but non-POD class types result in undefined behavior).省略号参数几乎可以匹配任何类型(但非 POD 类类型会导致未定义的行为)。

But that's just the beginning - if you are intrigued - I urge you to read the book and then the relevant portions of the standard :)但这只是开始 - 如果你感兴趣 - 我敦促你阅读这本书,然后阅读标准的相关部分:)

Addition from standard(N4687)从标准(N4687)添加

2 2

When comparing the basic forms of implicit conversion sequences (as defined in 16.3.3.1)比较隐式转换序列的基本形式时(如 16.3.3.1 中所定义)

— (2.1) a standard conversion sequence (16.3.3.1.1) is a better conversion sequence than a user-defined conversion sequence or an ellipsis conversion sequence, and — (2.1) 标准转换序列 (16.3.3.1.1) 是比用户定义的转换序列或省略号转换序列更好的转换序列,并且

— (2.2) a user-defined conversion sequence (16.3.3.1.2) is a better conversion sequence than an ellipsis conversion sequence (16.3.3.1.3). — (2.2) 用户定义的转换序列 (16.3.3.1.2) 是比省略号转换序列 (16.3.3.1.3) 更好的转换序列。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM