Вопрос по c++ – приоритет преобразования в с ++

4

У меня есть следующий код:

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 в A, используя конструктор преобразования, определенный выше. Почему я не получаю сообщение об ошибке? Каковы правила приоритета с кастингом?

Нотабене Я разместил выше код, который, я думаю, будет необходим для ответа на вопрос, но ниже я публикую весь код:

 #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);
 }
@Daniel: & quot; A :: A (int i_a) & quot; называется конструктором преобразования, потому что он будетimplicitly convert целое число для объекта. Если вы добавляете ключевое слово & quot; явное & quot; в определении ctor это неявное поведение преобразования удаляется -thenэто "просто" конструктор для A, который принимает int как параметр. j_random_hacker
отредактированные номера строк. Tom
@ Даниэль - я пытаюсь лучше понять, как работает С ++. Очевидно, что приведенный выше код не является действительно оптимальным. Meir
При размещении кода. НЕ добавляйте номера строк - это делает невозможным его компиляцию без дополнительного редактирования. Если вы хотите выделить номер строки, используйте комментарий. anon
В качестве идентификатора я бы не назвал «A :: A (int i_a)» конструктор преобразования, просто конструктор для A, который принимает int в качестве параметра. Кроме того, всегда хорошо вызывать h (любой h) с его точными параметрами. Если он принимает A (вторая функция), то почему бы не передать ему A? Например, h (A (1)); Daniel Daranas

Ваш Ответ

2   ответа
14

чтобы выбрать лучшего кандидата из всех возможных перегрузок - компилятор ранжирует все последовательности преобразования для каждого аргумента для каждого кандидата. Для функции, которая должна победить (быть выбранной в качестве лучшего кандидата), ее ранги преобразования для каждого аргумента должны быть лучше или равны ранжам преобразования любой другой функции для этого аргумента, и по крайней мере один ранг преобразования должен быть лучше, чем все преобразование другой функции ранжируется для определенного аргумента.

Определяемое пользователем преобразование (которое использует либо конструктор, либо оператор приведения) имеет один из худших возможных разрядов (только многоточие имеет худший ранг). Интегрально-плавающее преобразование имеет лучший ранг (список рейтингов см. Ниже).

Таким образом, компилятор предпочитает преобразовывать int - & gt; double (используя стандартное преобразование), чем преобразование int - & gt; A (используя пользовательское преобразование), и поэтому он выбирает f1.

Изменить: хотя & quot; Разрешение перегрузки & quot; работает в фоновом режиме, и большую часть времени выполняет именно то, что вы ожидаете (т.е. большинству программистов не нужно углубляться в технические аспекты) - если вы действительно хотите углубиться (но имейте в виду, что некоторые из более темных углов разрешения перегрузки считаются одним из самых хитрых моментов, когда авторы компиляторов получают точную информацию в компиляторе C ++). Шаблоны C ++: Полное руководство Дэвида Вандевурда и Николая М. Хосуттиса который содержит в приложении B одно из лучших введений в механизм разрешения перегрузки, которое я читал.

Вот выдержка из 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).

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*.

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.

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.

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).

Но это только начало - если вы заинтригованы - я призываю вас прочитать книгу, а затем соответствующие части стандарта :)

0

2

When comparing the basic forms of implicit conversion sequences (as defined in 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.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).

Похожие вопросы