Программирование >>  Инициализация объектов класса, структура 

1 ... 299 300 301 [ 302 ] 303 304 305 ... 395


Query::Query( const Query &rhs )

: loc( rhs. loc ), paren(rhs. paren)

if ( rhs. solution )

solution = new set<short>; set<short>::iterator

it = rhs. solution->begin(), end it = rhs. solution->end();

for ( ; ir != end it; ++it ) solution->insert( *it );

else solution = 0;

скопировать все разрешающее множество:

Однако, поскольку в нашей реализации разрешающее множество вычисляется по мере необходимости, копировать его сразу нет нужды. Назначение нашего копирующего конструктора - предотвратить копирование но умолчанию. Для этого достаточно инициализировать solution нулем:

NameQuery music = folk; осуществляется так:

1. Компилятор проверяет, есть ли в NameQuery явный копирующий конструктор. (Его нет. Поэтому необходимо применить почленную инициализацию по умолчанию.)

2. Далее компилятор проверяет, содержит ли объект NameQuery нодобъекта: базового класса. (Да, в нем имеется подобъект Query.)

3. Компилятор проверяет, определен ли в классе Query явный копирующий конструктор. (Нет, поэтому компилятор применит почленную инициализацию по умолчанию.)

4. Компилятор проверяет, содержит ли объект Query нодобъекты базового класса. (Нет.)

5. Компилятор просматривает все нестатические члены Query в порядке их объявления. (Если некоторый член не является объектом класса, как, например, paren и solution, то в объекте music он инициализируется соответствующим членом объекта folk. Если же является, как, скажем, loc, то к нему рекурсивно применяется шаг 1. В классе vector определен копирующий конструктор, который вызывается для инициализации music. loc с помощью folk. loc.)

6. Далее компилятор рассматривает нестатические члены NameQuery в порядке их объявления и находит объект класса string, где есть явный копирующий конструктор. Он и вызывается для инициализации music. name с помощью folk. name.

Инициализация по умолчанию music с помощью folk завершена. Она хороша во всех отношениях, кроме одного: если разрешить копирование по умолчанию члена solution, то программа, скорее всего, завершится аварийно. Поэтому вместо такой обработки мы предоставим явный копирующий конструктор класса Query. Можно, например,



Query::Query( const Query &rhs ) : loc( rhs. loc ) ,

paren(rhs. paren), solution( 0 )

Шаги 1 и 2 инициализации mIusiс c помощью folk те же, что и раньше. Но на шаге 3 компилятор обнаруживает, что в классе Query есть явный копирующий конструктор и вызывает его. Шаги 4 и 5 пропускаются, а шаг 6 выполняется, как и прежде.

На этот раз почленная инициализация music с помощью folk корректна. Реализовывать явный копирующий конструктор в NameQuery нет необходимости.

Объект производного класса NotQuery содержит подобъект базового Query и член op типа Query*, который указывает на операнд, размещенный в хипе. Деструктор NotQuery применяет к этому операнду оператор delete.

Для класса NotQuery почленная инициализация по умолчанию члена op небезопасна, поэтому необходим явный копирующий конструктор. В его реализации используется

inline NotQuery:: Notery( const Notery &rhs )

вызывается Query::Query( const Query &rhs ) : Query( rhs )

виртуальная функция clone() , которую мы определили в предыдущем разделе.

{ op = rhs. op->clone(); }

При почленной инициализации одного объекта класса NotQuery другим выполняются два шага:

1. Компилятор проверяет, определен ли в NotQuery явный копирующий конструктор. Да, определен.

2. Этот конструктор вызывается для почленной инициализации.

Вот и все. Ответственность за правильную инициализацию подобъекта базового класса и нестатических членов возлагается на копирующий конструктор NotQuery. (Классы AndQuery и OrQuery сходны с NotQuery, поэтому мы оставляем их в качестве упражнения для читателей.)

Почленное присваивание аналогично почленной инициализации. Если имеется явный копирующий оператор присваивания, то он вызывается для выполнения присваивания одного объекта класса другому. В противном случае применяется почленное присваивание по умолчанию.

Если базовый класс есть, то сначала с помощью копирующего оператора присваивания почленно присваивается подобъект данного класса, иначе такое присваивание рекурсивно применяется к базовым классам и членам подобъекта базового класса.

Просматриваются все нестатические члены в порядке их объявления. Если член не является объектом класса, то его значение справа от знака равенства копируется в значение соответствующего члена слева от знака равенства. Если же член является объектом класса, в котором определен явный копирующий оператор присваивания, то он и вызывается. В противном случае к базовым классам и членам объекта-члена применяется почленное присваивание по умолчанию.



Query& Query::

operator=( const Query &rhs ) {

предотвратить присваивание самому себе if ( &rhs != this ) {

paren = rhs. paren; loc = rhs. loc; delete solution; solution = 0;

return *this;

достаточно предотвратить копирование по умолчанию: };

В классе NameQuery явный копирующий оператор присваивания не нужен. Присваивание одного объекта NameQuery другому выполняется в два шага:

1. Для присваивания подобъектов Query двух объектов NameQuery вызывается явный копирующий оператор присваивания класса Query.

2. Для присваивания членов string вызывается явный копирующий оператор присваивания этого класса.

Для объектов NameQuery вполне достаточно почленного присваивания по умолчанию.

В каждом из классов NotQuery, AndQuery и OrQuery для безопасного копирования операндов требуется явный копирующий оператор присваивания. Вот его реализация для

inline NotQuery& NotQuery::

operator=( const NotQuery &rhs ) {

предотвратить присваивание самому себе if ( &rhs != this ) {

вызвать копирщий оператор присваивания Query this->Query::operator=( rhs );

скопировать операнд

op = rhs. op->clone();

return *this;

NotQuery:

В отличие от копирующего конструктора, в копирующем операторе присваивания нет специальной части, через которую вызывается аналогичный оператор базового класса. Для этого используются две синтаксических конструкции: явный вызов, продемонстрированный выше, и явное приведение типа, как в следующем примере:

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



1 ... 299 300 301 [ 302 ] 303 304 305 ... 395

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика