Неявное литье переполнения стека

Рассмотрим этот случай:

ClassA obA;
ClassB obB;

obA = obB;

Правильно ли, что если ClassA имеет конструктор, который имеет параметр типа ClassB, это будет называться в этом случае?

Если есть перегруженный оператор приведения ClassB — который преобразует ClassB Возражать ClassA объект, метод оператора будет вызван. Если есть соответствующий конструктор и перегруженный оператор приведения, какой из них будет вызван? Где я могу прочитать об этом?

3

Решение

Правильно ли, что если 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 где вы можете узнать больше.

3

Другие решения

Этот код:

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

который будет называться в вашем случае.

3

По вопросам рекламы [email protected]