Рассмотрим этот случай:
ClassA obA;
ClassB obB;
obA = obB;
Правильно ли, что если ClassA
имеет конструктор, который имеет параметр типа ClassB
, это будет называться в этом случае?
Если есть перегруженный оператор приведения ClassB
— который преобразует ClassB
Возражать ClassA
объект, метод оператора будет вызван. Если есть соответствующий конструктор и перегруженный оператор приведения, какой из них будет вызван? Где я могу прочитать об этом?
Правильно ли, что если
ClassA
имеет конструктор, который имеет параметр типаClassB
, это будет называться в этом случае?
Да, конструкторы рассматриваются для неявных преобразований типов:
Преобразования типов объектов класса могут быть определены конструкторами и по функциям преобразования. Эти
преобразования называются пользовательскими преобразованиями и используются для неявных преобразований типов (раздел 4), для
инициализация (8.5) и для явных преобразований типов (5.4, 5.2.9).
Конструктор с подписью ClassA::ClassA(ClassB)
называется превращающего конструктор. Во время вызова функции, такого как назначение, конструкторы и определяемые пользователем операторы преобразования компилируются в набор перегрузки, и для преобразования выбирается лучший из них.
Если выбран конструктор: Если тип источника является типом по значению, он создает значение типа источника (ClassA
) инициализируется с типом типа назначения (ClassB
), и это используется для инициализации параметра. Если тип источника является ссылкой, правила инициализации ссылок используются.
Операторы присваивания неявно генерируются в ClassA
(при условии, что они не были переопределены). Они есть:
ClassA& operator=(ClassA const&);
ClassA& operator=(ClassA &&);
Последовательность неявного преобразования может выбрать конструктор или функцию преобразования для преобразования ClassB -> ClassA const&
или же ClassB -> ClassA&&
,
Однако в этом случае, согласно вашему сценарию, преобразование не сможет быть успешным, поскольку это будет неоднозначно. Рассматривать:
struct B { operator struct A(); };
struct A {
A() = default;
A(B) {}
};
B::operator A() { return A(); }
int main()
{
A a; B b;
a = b; // Error! Ambiguous conversion
}
И то и другое A::A(B)
а также B::operator A()
обе жизнеспособные функции преобразования, чтобы использовать для преобразования. Таким образом, преобразование неоднозначно, и мы получаем ошибку компиляции.
Определяемые пользователем преобразования применяются только в том случае, если они однозначны (10.2, 12.3.2).
Если мы изменим сигнатуру конвертирующего конструктора в классе A
в A::A(B const&)
затем оператор преобразования в B
будет использоваться, потому что A
Для конструктора требуется преобразование квалификации (добавление const
).
Есть нить на cppreference где вы можете узнать больше.
Этот код:
ClassA obA;
ClassB obB;
obA = obB;
это не то, что вы думаете, это (*). Этот код:
ClassB obB;
ClassA obA = obB;
будет работать (как предусмотрено), если:
1. ClassA
имеет конструктор, который принимает ClassB
в качестве параметра:
class ClassA
{
public:
ClassA(const ClassB& b)
{
//construct *this from b
}
};
2. ClassB
определил оператор преобразования в тип:
class ClassB
{
public:
operator ClassA() const
{
//construct ClassA from *this
}
};
Если в ClassA есть перегруженный оператор приведения, у которого есть параметр типа ClassB […].
Вы имели в виду конструктор, не оператор кастинга, право? Вы пытаетесь конвертировать ClassA
в ClassB
поэтому операторы преобразования из ClassA
не имеют значения в этом случае.
(*) Вы назначаете obB
в obA
после obA
Это конструкция, поэтому в вашем случае применим только второй пункт. Вы также можете заставить его работать, добавив оператор присваивания:
3.
class ClassA
{
public:
ClassA& operator=(const ClassB& b)
{
//assign b to *this
}
};
который будет называться в вашем случае.