- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Язык программирования C++. Пятое издание - Стенли Липпман
Шрифт:
Интервал:
Закладка:
// возвращает объединение наборов результатов своих операндов
QueryResult
OrQuery::eval(const TextQuery& text) const {
// виртуальные вызовы через члены Query, lhs и rhs
// вызовы eval() возвращают QueryResult для каждого операнда
auto right = rhs.eval(text), left = lhs.eval(text);
// копировать номера строк левого операнда в результирующий набор
auto ret_lines =
make_shared<set<line_no>>(left.begin(), left.end());
// вставить строки из правого операнда
ret_lines->insert(right.begin(), right.end());
// возвратить новый QueryResult, представляющий объединение lhs и rhs
return QueryResult(rep(), ret_lines, left.get_file());
}
Набор ret_lines инициализируется с использования того конструктора, который получает пару итераторов. Функции-члены begin() и end() класса QueryResult возвращают итераторы на номера строк набора. Таким образом, набор ret_lines создается при копировании элементов из набора left. Затем для вставки элементов из набора right вызывается функция insert(). После этого вызова набор ret_lines содержит номера строк из наборов, которые присутствуют в наборах left или right.
Функция eval() завершает работу, создавая и возвращая объект класса QueryResult, представляющий объединение соответствий. Конструктор QueryResult() (см. раздел 12.3.2) получает три аргумента: строку, представляющую запрос, указатель shared_ptr на набор соответствующих номеров строк и указатель shared_ptr на вектор, представляющий входной файл. Вызов функции rep() позволяет создать строку, а вызов функции get_file() — получить указатель shared_ptr на файл. Поскольку оба набора, left и right, относятся к тому же файлу, не имеет значения, который из них использовать для функции get_file().
Функция AndQuery::eval()Версия функции eval() класса AndQuery подобна версии класса OrQuery, за исключением того, что она использует библиотечный алгоритм для поиска строк, общих для обоих запросов:
// возвращает пересечение наборов результатов своих операндов
QueryResult
AndQuery::eval(const TextQuery& text) const {
// виртуальный вызов через операнды класса Query для получения
// результирующих наборов для операндов
auto left = lhs.eval(text), right = rhs.eval(text);
// набор для хранения пересечения left и right
auto ret_lines = make_shared<set<line_no>>();
// выводит пересечение двух диапазонов в итератор назначения
// итератор назначения в этом вызове добавляет элементы в ret
set_intersection(left.begin(), left.end(),
right.begin(), right.end(),
inserter(*ret_lines, ret_lines->begin()));
return QueryResult(rep(), ret_lines, left.get_file());
}
Здесь для объединения двух наборов используется библиотечный алгоритм set_intersection, описанный в приложении А.2.8.
Алгоритм set_intersection получает пять итераторов. Первые четыре он использует для обозначения двух исходных последовательностей (см. раздел 10.5.2). Его последний аргумент обозначает получателя. Алгоритм выводит элементы, присутствующие в обеих исходных последовательностях, в результирующую.
В данном вызове получателем является итератор вставки (см. раздел 10.4.1). Результатом записи алгоритмом set_intersection в этот итератор будет вставка нового элемента в набор ret_lines.
Подобно функции eval() класса OrQuery, эта завершается созданием и возвращением объекта класса QueryResult, представляющего объединение соответствий.
Функция NotQuery::eval()Функция eval() класса NotQuery ищет в тексте все строки, в которых операнд отсутствует.
// возвращает строки, отсутствующие в наборе результатов
// операнда QueryResult
NotQuery::eval(const TextQuery& text) const {
// виртуальный вызов для вычисления операнда Query
auto result = query.eval(text);
// начать с пустого результирующего набора данных
auto ret_lines = make_shared<set<line_no>>();
// следует перебрать строки, в которых присутствует операнд
auto beg = result.begin(), end = result.end();
// для каждой строки во входном файле, если она отсутствует
// в result, добавить ее номер в ret_lines
auto sz = result.get_file()->size();
for (size_t n = 0; n != sz; ++n) {
// если не обработаны все строки в result
// проверить присутствие этой строки
if (beg == end || *beg != n)
ret_lines->insert(n); // если нет в result, добавить строку
else if (beg != end)
++beg; // в противном случае получить следующий номер строки
// в result, если она есть
}
return QueryResult(rep(), ret_lines, result.get_file());
}
Как и другие функции eval(), данная начинается с вызова функции eval() операнда объекта. Этот вызов возвращает объект класса QueryResult, содержащий номера строк, в которых присутствует операнд. Однако вернуть необходимо набор номеров строк, в которых операнд отсутствует. Как и в других функциях eval(), данная начинается с вызова функции eval() операнда объекта. Вызов возвращает объект класса QueryResult, содержащий номера строк, в которых операнд присутствует, но необходимы номера строки, на которых операнд отсутствует. Поэтому следует найти в файле все строки, отсутствующие в наборе результатов.
Набор создается в результате последовательного перебора целых чисел до размера входного файла. Каждое число, отсутствующее в наборе result, помещается в набор ret_lines. Итераторы beg и end устанавливаются на первый и следующий после последнего элементы в наборе result. Поскольку речь идет о наборе, при переборе номера строк будут следовать в порядке возрастания.
Тело цикла проверяет наличие текущего числа в наборе result. Если его нет, то число добавляется в набор ret_lines. Если он есть, осуществляется приращение итератора beg набора result.
Как только все номера строк будут обработаны, возвращается объект класса QueryResult, содержащий набор ret_lines наряду с результатами выполнения функций rep() и get_file(), как и у предыдущих функций eval().
Упражнения раздела 15.9.4Упражнение 15.39. Реализуйте классы Query и Query_base. Проверьте приложение на вычислении и выводе запроса, представленного на рис. 15.3.
Упражнение 15.40. Что будет, если параметр rhs функции-члена eval() класса OrQuery возвратит пустой набор? Что, если так поступит ее параметр lhs? Что если и rhs, и lhs возвратят пустые множества?
Упражнение 15.41. Переделайте свои классы так, чтобы использовать встроенные указатели на класс Query_base, а не интеллектуальные указатели shared_ptr. Помните, что ваши классы больше не смогут использовать синтезируемые функции-члены управления копированием.
Упражнение 15.42. Разработайте и реализуйте одно из следующих дополнений.
(a) Организуйте вывод слов только однажды в предложении, а не однажды в строке.
(b) Снабдите систему историей, позволяющей пользователю обратиться к предыдущему запросу по номеру, а также добавлять или комбинировать их с другими.
(c) Позвольте пользователю ограничивать результаты так, чтобы отображался набор соответствий только в заданном диапазоне строк.
Резюме
Наследование позволяет создавать новые классы, которые совместно используют возможности их базового класса (классов), но при необходимости могут их переопределить или дополнить. Динамическое связывание позволяет компилятору во время выполнения выбрать версию применяемой функции на основании динамического типа объекта. Комбинация наследования и динамического связывания позволяет создавать программы, которые либо не зависят от типа объекта, либо имеют поведение, зависящие от типа объекта.
В языке С++ динамическое связывание применимо только к тем функциям, которые объявлены виртуальными и вызываются при помощи ссылок или указателей.
Объекты производных классов состоят из части (частей) базового класса и части производного. Поскольку частью объекта производного класса является объект базового, ссылку или указатель на объект производного класса вполне можно преобразовать в ссылку или указатель на его доступный базовый класс.

