Страницы

Поиск по вопросам

вторник, 20 ноября 2018 г.

Как программа копирует экземпляры разных классов?

Есть два класса: A и B.
Если производится копирование обьектов одного и того же класса, то вызывается конструктор копирования и копирует соответствующие поля. А вот если произвести такое:
A a; B b;
a = (A)b;
Как работает копирование в этом случае?


Ответ

Если в классе B имеется доступный оператор преобразования типов из типа класса B в тип класса A, то он вызывается в выражении приведения типа (A)b, результатом которого является временный объект типа A. Этот временный объект присваивается объекту a с помощью копирующего или перемещающего оператора присваивания в предложении
a = (A)b;
Вот демонстрационная программа
#include
struct A { A & operator =( const A & ) { std::cout << "A::operator =" << std::endl; return *this; } };
struct B { operator A() const { std::cout << "operator B::A()" << std::endl; return A(); } };
int main() { A a; B b;
a = ( A )b;
return 0; }
Ее вывод на консоль
operator B::A() A::operator =
Оператор преобразования может быть объявлен также со спецификатором функции explicit. Например,
explicit operator A() const;
Или более "запутанный" пример преобразований, когда оператор преобразования перегружен для lvalue и rvalue
#include
struct A { A() { std::cout << "A::A()" << std::endl; }
A( const A & ) { std::cout << "A::A( const A & )" << std::endl; }
A & operator =( const A & ) { std::cout << "A::operator =( const A & )" << std::endl; return *this; }
A & operator =( A && ) { std::cout << "A::operator =( A && )" << std::endl; return *this; } };
struct B { explicit operator A() const & { std::cout << "operator A() &" << std::endl; return A(); }
explicit operator A() const && { std::cout << "operator A() &&" << std::endl; return A(); } };
int main() { A a; B b;
a = ( A )b;
std::cout << std::endl;
a = ( A )B();
return 0; }
Вывод этой программы на консоль
A::A() operator A() & A::A() A::operator =( A && )
operator A() && A::A() A::operator =( A && )
Например, для предложения
a = ( A )B();
вызывается оператор преобразования для rvalue временного объекта, созданного вызовом B()
operator A() &&
Затем внутри этого оператора создается временный объект типа A
A::A()
Этот временный объект с помощью перемещающего оператора присваивания присваивается объекту a
A::operator =( A && )
Самый простой вариант - это когда в классе A имеется конструктор преобразования. Например,
#include
struct A { A() {}
explicit A( const struct B & );
A & operator =( const A & ) { std::cout << "A::operator =( const A & )" << std::endl; return *this; }
};
struct B { };
A::A( const B & ) { std::cout << "A::A( const B & )" << std::endl; }
int main() { A a; B b;
a = ( A )b;
return 0; }
Вывод программы на консоль
A::A( const B & ) A::operator =( const A & )
В определении класса A объявлен преобразующий конструктор
explicit A( const struct B & );
который вызывается при приведении типов в выражении ( A )b
И, наконец, если класс B является производным от класса A, то вы можете просто записать
a = b;
В этом случае объект класса B неявно преобразуется в объект класса A и вызывается копирующий оператор присваивания класса A

Комментариев нет:

Отправить комментарий