Если базовый класс есть, то сначала с помощью копирующего оператора присваивания почленно присваивается подобъект данного класса, иначе такое присваивание рекурсивно применяется к базовым классам и членам подобъекта базового класса.
Просматриваются все нестатические члены в порядке их объявления. Если член не является объектом класса, то его значение справа от знака равенства копируется в значение соответствующего члена слева от знака равенства. Если же член является объектом класса, в котором определен явный копирующий оператор присваивания, то он и вызывается. В противном случае к базовым классам и членам объекта-члена применяется почленное присваивание по умолчанию.
Вот как выглядит копирующий оператор присваивания для нашего объекта Query. Еще раз отметим, что в этом месте необязательно копировать разрешающее множество, достаточно предотвратить копирование по умолчанию:
Query&
Query::
operator=( const Query &rhs )
{
// предотвратить присваивание самому себе
if ( &rhs != this )
{
_paren = rhs._paren;
_loc = rhs._loc;
delete _solution;
_solution = 0;
}
return *this;
};
В классе NameQuery явный копирующий оператор присваивания не нужен. Присваивание одного объекта NameQuery другому выполняется в два шага:
Для присваивания подобъектов Query двух объектов NameQuery вызывается явный копирующий оператор присваивания класса Query.
Для присваивания членов string вызывается явный копирующий оператор присваивания этого класса.
Для объектов NameQuery вполне достаточно почленного присваивания по умолчанию.
В каждом из классов NotQuery, AndQuery и OrQuery для безопасного копирования операндов требуется явный копирующий оператор присваивания. Вот его реализация для NotQuery:
inline NotQuery&
NotQuery::
operator=( const NotQuery &rhs )
{
// предотвратить присваивание самому себе
if ( &rhs != this )
{
// вызвать копирующий оператор присваивания Query
this-Query::operator=( rhs );
// скопировать операнд
_op = rhs._op-clone();
}
return *this;
}
В отличие от копирующего конструктора, в копирующем операторе присваивания нет специальной части, через которую вызывается аналогичный оператор базового класса. Для этого используются две синтаксических конструкции: явный вызов, продемонстрированный выше, и явное приведение типа, как в следующем примере:
(*static_castQuery*(this)) = rhs;
(Реализация копирующих операторов присваивания в классах AndQuery и OrQuery выглядит так же, поэтому мы оставим ее в качестве упражнения.)
Ниже предложена небольшая программа для тестирования данной реализации. Мы создаем или копируем объект, а затем распечатываем его.
#include "
Query.h"
int
main()
{
NameQuery nm( "alice" );
NameQuery nm( "emma" );
NotQuery nq1( &nm );
cout "notQuery 1: " nq1 endl;
NotQuery nq2( nq1 );
cout "notQuery 2: " nq2 endl;
NotQuery nq3( &nm2 );
cout "notQuery 3: " nq3 endl;
nq3 = nq2;
cout "notQuery 3 присвоено значение nq2: " nq3 endl;
AndQuery aq( &nq1, &nm2 );
cout "AndQuery : " aq endl;
AndQuery aq2( aq );
cout "AndQuery 2: " aq2 endl;
AndQuery aq3( &nm, &nm2 );
cout "AndQuery 3: " aq3 endl;
aq2 = aq3;
cout "AndQuery 2 после присваивания: " aq2 endl;
}
После компиляции и запуска программа печатает следующее:
notQuery 1: ! alice
notQuery 2: ! alice
notQuery 3: ! emma
notQuery 3 присвоено значение nq2: ! alice
AndQuery : ! alice && emma
AndQuery 2: ! alice && emma
AndQuery 3: alice && emma
AndQuery 2 после присваивания: alice && emma
Упражнение 17.18
Реализуйте копирующие конструкторы в классах AndQuery и OrQuery.
Упражнение 17.19
Реализуйте копирующие операторы присваивания в классах AndQuery и OrQuery.
Упражнение 17.20