17.5.7. Почти виртуальный оператор new
17.5.7. Почти виртуальный оператор new
Если дан указатель на один из конкретных подтипов запроса, то разместить в хипе дубликат объекта несложно:
NotQuery *pnq;
// установить pnq ...
// оператор new вызывает
// копирующий конструктор NotQuery ...
NotQuery *pnq2 = new NotQuery( *pnq );
Если же у нас есть только указатель на абстрактный класс Query, то задача создания дубликата становится куда менее тривиальной:
const Query *pq = pnq-op();
// как получить дубликат pq?
Если бы позволялось объявить виртуальный экземпляр оператора new, то проблема была бы решена, поскольку автоматически вызывался бы нужный экземпляр. К сожалению, это невозможно: new - статическая функция-член, которая применяется к неструктурированной памяти еще до конструирования объекта класса (см. раздел 15.8).
Но хотя оператор new нельзя сделать виртуальным, разрешается создать его суррогат, который будет выделять память из хипа и копировать туда объекты, - clone():
class Query {
public:
virtual Query *clone() = 0;
// ...
};
Вот как он может быть реализован в классе NameQuery:
class NameQuery : public Query {
public:
virtual Query *clone()
// вызывается копирующий конструктор класса NameQuery
{ return new NameQuery( *this ); }
// ...
};
Это работает правильно, если тип целевого указателя Query*:
Query *pq = new NameQuery( "valery" );
Query *pq2 = pq-clone();
Если же его тип равен NameQuery*, нужно привести возвращенный указатель типа Query* назад к типу NameQuery*:
NameQuery *pnq = new NameQuery( "Rilke" );
NameQuery *pnq2 =
static_castNameQuery*( pnq-clone() );
(Причина, по которой необходимо преобразование типа, объясняется в разделе 19.1.1.)
Как правило, тип значения, возвращаемого реализацией виртуальной функции в производном классе, должен совпадать с типом, возвращаемым ее реализацией в базовом. Исключение, о котором мы уже упоминали, призвано поддержать рассмотренную ситуацию. Если виртуальная функция в базовом классе возвращает значение некоторого типа класса (либо указатель или ссылку на тип класса), то ее реализация в производном может возвращать значение, тип которого является производным от этого класса с открытым типом наследования (то же относится к ссылкам и указателям):
class NameQuery : public Query {
public:
virtual NameQuery *clone()
{ return new NameQuery( *this ); }
// ...
};
Теперь pq2 и pnq2 можно инициализировать без явного приведения типов:
// Query *pq = new NameQuery( "Broch" );
Query *pq2 = pq-clone(); // правильно
// NameQuery *pnq = new NameQuery( "Rilke" );
NameQuery *pnq2 = pnq-clone(); // правильно
Так выглядит реализация clone() в классе NotQuery:
class NotQuery : public Query {
public:
virtual NotQuery *clone()
{ return new NotQuery( *this ); }
// ...
};
Реализации в AndQuery и OrQuery аналогичны. Чтобы эти реализации clone() работали правильно, в классах NotQuery, AndQuery и OrQuery должны быть явно определены копирующие конструкторы. (Мы займемся этим в разделе 17.6.)
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКЧитайте также
Не нужно прерывать, мы почти закончили!
Не нужно прерывать, мы почти закончили! В этой главе были рассмотрены прерывания, аппаратные ресурсы, которые используются устройствами для подачи асинхронных сигналов процессору. Прерывания используются аппаратным обеспечением, чтобы прервать работу операционной
(3.1) Как удалить ненужные компоненты W2k? В Add/Remove programs почти ничего нет.
(3.1) Как удалить ненужные компоненты W2k? В Add/Remove programs почти ничего нет. Чтобы в Add/Remove programs появились все компоненты, которые можно удалить, надо найти файлик sysoc.inf в WINNTINF и подредактировать его. Убрать слова HIDE или hide, везде где они встретятся. После этого, в Add/Remove Windows components
Виртуальный сервер
Виртуальный сервер Иметь компьютер, круглосуточно подключенный к Интернету по скоростной линии связи, довольно накладно и не всегда по карману желающим поместить свою информацию в Интернете. Выходом из сложившейся ситуации может стать использование виртуального
Blogger relations (почти манифест)
Blogger relations (почти манифест) Метки: как общаться с блоггерамиНаверное, вы уже поняли, что неправильно оставлять блоггеров за бортом ваших маркетинговых мероприятий. Но как включить эту когорту разнокалиберных личностей в маркетинговые коммуникации?Информация дешевеет, а
11.5. Виртуальный узел FTP
11.5. Виртуальный узел FTP В этом разделе книги пойдет речь о конфигурировании виртуального FTP-сервера. Создание виртуального FTP-сервера будет происходить с использованием сервера ProFTP.Для начала определимся, что такое виртуальный сервер? Как и подразумевает слово
15.4. Виртуальный узел FTP
15.4. Виртуальный узел FTP Виртуальный сервер — это сервер, не существующий физически, но представляющийся пользователю как реальный сервер. ОС Linux может поддерживать несколько IP-адресов, благодаря чему имеется возможность создать виртуальные узлы. Если вы располагаете
Виртуальный статут
Виртуальный статут Наш кириллический домен выходит больше похожим на домен GOV, чем на домен COM. Поэтому почта. рф – вполне логичный адрес для сайта, например, связанного с Федеральной почтовой связью Российской Федерации. А БАНК.РФ, в таком случае, – это адрес Центрального
Урок 21 Skype, или Как звонить подругам почти бесплатно
Урок 21 Skype, или Как звонить подругам почти бесплатно Ну что, вы еще не устали от общения? Я думаю, нет, уж чем-чем, а общением женщину не напугаешь, тут чем больше, тем лучше.Значит, у нас уже есть форумы, блог и в уголке компьютера мирно зеленеет «Аськин» цветочек. Счастье?
Виртуальный фотоальбом
Виртуальный фотоальбом Фотографиями вам необходимо обзавестись в любом случае – надеюсь, вы понимаете, что даже идеально составленный текст объявления или резюме поможет вам сделать лишь первый шаг к знакомству. А бывает, что без фото невозможен и он – объявление, не
Правило 52: Если вы написали оператор new с размещением, напишите и соответствующий оператор delete
Правило 52: Если вы написали оператор new с размещением, напишите и соответствующий оператор delete Операторы new и delete с размещением встречаются в C++ не слишком часто, поэтому в том, что вы с ними не знакомы, нет ничего страшного. Вспомните (правила 16 и 17), что когда вы пишете такое
1. Оператор Select – базовый оператор языка структурированных запросов
1. Оператор Select – базовый оператор языка структурированных запросов Центральное место в языке структурированных запросов SQL занимает оператор Select, с помощью которого реализуется самая востребованная операция при работе с базами данных – запросы.Оператор Select
15.8.2. Оператор размещения new() и оператор delete()
15.8.2. Оператор размещения new() и оператор delete() Оператор-член new() может быть перегружен при условии, что все объявления имеют разные списки параметров. Первый параметр должен иметь тип size_t:class Screen {public:void *operator new( size_t );void *operator new( size_t, Screen * );// ...};Остальные параметры
О пузометрии: спустя почти полгода
О пузометрии: спустя почти полгода Апрель 29, 2013Когда речь заходит о systemd, сторонники этого менеджера инициализации говорят о массе его преимуществ по сравнению и с древним sysvinit, и с upstart, разработанным для Ubuntu. Многие из этих преимуществ выглядят субъективными. Например,
Виртуальный фотоальбом
Виртуальный фотоальбом Массовое распространение цифровой фотографии в последнее время привело к тому, что многие люди стремятся перевести даже обычные фотографии в цифровой вид, чтобы добавить их к уже имеющимся цифровым и создавать виртуальные фотоальбомы.Конечно,
Почти пришли Автор: Тимофей Бахвалов.
Почти пришли Автор: Тимофей Бахвалов. © 2004, Издательский дом | http://www.computerra.ru/Журнал «Домашний компьютер» | http://dk.compulenta.ru/Этот материал Вы всегда сможете найти по его постоянному адресу: /2006/121/280069/Пока Microsoft Xbox 360, торопливо вытолкнутая хозяевами на арену, под светом