Может ли аргумент конвертирующего конструктора быть неявно преобразованным? - PullRequest
1 голос
/ 07 июня 2019

Сейчас я работаю над проектом, в котором конвертируемость между двумя классами (A и B) крайне желательна. Я создал функцию myFunc (), которая принимает объект класса A в качестве аргумента, и передал ей объект класса B.

Причина, по которой я ожидал, что это сработает, заключается в том, что B можно неявно преобразовать в целое число, а A можно неявно построить с помощью целого числа. Я ожидал, что эти два процесса произойдут так, что объект класса B будет неявно преобразован в объект класса A. Это не так.

Когда я пытаюсь передать объект класса B в myFunc (), я получаю ошибку: error: could not convert 'b' from 'B' to 'A'.

Интересно, однако, что я могу передать объект класса B, который я явно приводил к целому числу, или явно сконструированный объект класса A, который принимает объект класса B в качестве аргумента. Кажется, что только один неявный процесс (будь то конструктор преобразования или неявное преобразование) может происходить в одной строке. Почему это так? Есть ли способ обойти эту проблему?

Я знаю, что простым решением было бы создать конструктор в A, который принимает объект класса B в качестве аргумента, или создать оператор в B, который преобразует объект класса B в объект класса A. Однако в моих целях эти решения не должны использоваться, если это не является абсолютно необходимым.

Я все еще изучаю C ++ (я пришел с Java). Надеюсь, приведенный ниже код пояснит, о чем я говорю. Спасибо за ваш отзыв заранее.

#include <iostream>

// objects of class A can be (implicitly) constructed with an int
struct A {
    A(int) {}
};

// objects of class B can be (implicitly) converted to an int
struct B {
    B(int) {}
    operator int() { return 0; }
};

// myFunc takes an object of class A
void myFunc(A)
{ }

// why can't myFunc convert the argument b like the following: B -> int -> A?
int main()
{
    B b(5);

    // These work:
    myFunc((int) b);
    myFunc(A(b));

    // This does not:
    myFunc(b);
}

Примечание. Приведенный выше код должен правильно компилироваться до тех пор, пока myFunc(b); не будет закомментирован.

1 Ответ

1 голос
/ 07 июня 2019

То, что вы ищете, называется последовательность преобразования в C ++. Чтобы перейти от одного типа к другому, может быть только ограниченное количество шагов. Важно отметить, что от каждой из возможных категорий может быть не более одного шага. Например. Вы можете иметь не более одного числового продвижения (например, от short до long.). Важно, что в вашем примере может быть не более одного пользовательского преобразования . Это или a конструктор преобразования (Foo::Foo(Bar)) или a функция преобразования (Bar::operator Foo). Вашему примеру нужны оба.

...