Это очень просто: неявная конвертируемость (для пользовательских типов) не является транзитивным свойством в C ++. То есть, хотя A
конвертируется в int
, а int
конвертируется в B
, это означает, что не само по себе означает, что A
конвертируется в B
. Не существует допустимой последовательности неявного преобразования из A
в B
, поэтому A
не может быть преобразовано в B
.
Для инициализации копирования требуется неявная конвертируемость между типом выражения инициализации и типом инициализируется. Поскольку A
не конвертируется в B
, b1
не компилируется.
Каждый раз, когда вы видите {}
как часть инициализации, подобной этой, это означает, что объект, к которому он применяется, в соответствии с go некоторая форма инициализации списка, которая отличается от других форм инициализации.
b2
не выполняет "прямую инициализацию". Он выполняет прямую список инициализацию, которая является одной из двух форм инициализации списка. Правила инициализации списка, в этом случае, в конечном итоге сводятся к использованию разрешения перегрузки для набора конструкторов для B
. Существует конструктор B
, который можно вызывать с помощью A
, поскольку этот вызов может происходить посредством неявного преобразования int
в *1034*.
b3
not "copy" инициализация "; это копия список инициализация, которая абсолютно не связана с «копией инициализации». Copy-list-initialization идентична прямой-list-initialization точно с двумя исключениями, ни одно из которых не применимо к этому случаю. Так что он делает то же самое, что и b2
.