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

1 ... 297 298 299 [ 300 ] 301 302 303 ... 395


==> fiery && bird

fiery ( 1 ) lines match

display location vector:

first: 2 second: 2

first: 2 second: 8

bird ( 1 ) lines match

display location vector:

first: 2 second: 3

first: 2 second: 9

fiery && bird ( 1 ) lines match

display location vector:

first: 2 second: 2

first: 2 second: 3

first: 2 second: 8

first: 2 second: 9

Requested query: fiery && bird

( 3 ) like a fiery bird in flight. A beautiful fiery bird, he tells her,

Приведем трассировку выполнения составного запроса, включающего как И, так и ИЛИ. Показаны векторы позиций каждого операнда, а также результирующий вектор:

==> fiery && ( bird untamed )

fiery ( 1 ) lines match

display location vector:

first: 2 second: 3

first: 2 second: 8

bird ( 1 ) lines match

display location vector:

first: 2 second: 3

first: 2 second: 9

untamed ( 1 ) lines match

display location vector:

first: 3 second: 2

( bird untamed ) ( 2 ) lines match

display location vector:

first: 2 second: 3

first: 2 second: 9

first: 3 second: 2

fiery && ( bird untamed ) ( 1 ) lines match

display location vector:

first: 2 second: 2

first: 2 second: 3

first: 2 second: 8

first: 2 second: 9

Requested query: fiery && ( bird untamed )

( 3 ) like a fiery bird in flight. A beautiful

fiery bird, he tells her,

17.5.7. Почти виртуальный оператор new

Если дан указатель на один из конкретных подтипов запроса, то разместить в хипе

NotQuery *pnq;

установить pnq

оператор new вызывает копирующий конструктор NotQuery ...

дубликат объекта несложно:

NotQuery *pnq2 = new NotQuery( *pnq );

А так выглядит трассировка выполнения запроса AAndQuery, в которой м1 выводим векторы позиций обоих операндов и результирующий вектор:



class Query {

public:

virtual Query *clone() = 0;

...

который будет выделять память из хипа и копировать туда объекты, - clone():

class NameQuery : public Query { public:

virtual Query *clone()

вызается копирщий конструктор класса NameQuery { return new NameQuery( *this ); }

...

Вот как он может быть реализован в классе NameQuery:

Query *pq = new NameQuery( valery );

Это работает правильно, если тип целевого указателя Query*:

Query *pq2 = pq->clone();

Если же его тип равен NameQuery*, нужно привести возвращенный указатель типа

NameQuery *pnq NameQuery *pnq2

= new NameQuery( Rilke );

Query* назад к типу NameQuery*:

static cast<NameQuery*>( pnq->clone() );

(Причина, по которой необходимо преобразование типа, объясняется в разделе 19.1.1.)

Если же у нас есть только указатель на абстрактный класс Query, то задача создания

const Query *pq = pnq->op();

дубликата становится куда менее тривиальной:

/ / как получить дубкат pq?

Если бы позволялось объявить виртуальный экземпляр оператора new, то проблема была бы решена, поскольку автоматически вызывался бы нужный экземпляр. К сожалению, это невозможно: new - статическая функция-член, которая применяется к неструктурированной памяти еще до конструирования объекта класса (см. раздел 15.8).

Но хотя оператор new нельзя сделать виртуальным, разрешается создать его суррогат,



class NameQuery : public Query {

public:

virtual NameQuery *clone()

{ return new NameQuery( *this ); }

...

открытым типом наследования (то же относится к ссылкам и указателям):

Query *pq = new NameQuery( Broch ); Query *pq2 = pq->clone(); правильно

NameQuery *pnq = new NameQuery( Rilke );

Теперь pq2 и pnq2 можно инициализировать без явного приведения типов:

NameQuery *pnq2 = pnq->clone(); правильно

class NotQuery : public Query {

public:

virtual NotQuery *clone()

{ return new NotQuery( *this ); }

...

Так выглядит реализация clone() в классе NotQuery: };

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

17.5.8. Виртуальные функции, конструкторы и деструкторы

Как мы видели в разделе 17.4, для объекта производного класса сначала вызывается конструктор базового, а затем производного класса. Например, при таком определении объекта NameQuery

NameQuery poet( Orlen ); сначала будет вызван конструктор Query, а потом NameQuery.

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



1 ... 297 298 299 [ 300 ] 301 302 303 ... 395

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