ret_lines->insert(n); //
else if (beg != end)
++beg; //
//
}
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.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) Позвольте пользователю ограничивать результаты так, чтобы отображался набор соответствий только в заданном диапазоне строк.
Резюме
Наследование позволяет создавать новые классы, которые совместно используют возможности их базового класса (классов), но при необходимости могут их переопределить или дополнить. Динамическое связывание позволяет компилятору во время выполнения выбрать версию применяемой функции на основании динамического типа объекта. Комбинация наследования и динамического связывания позволяет создавать программы, которые либо не зависят от типа объекта, либо имеют поведение, зависящие от типа объекта.
В языке С++ динамическое связывание применимо
Объекты производных классов состоят из части (частей) базового класса и части производного. Поскольку частью объекта производного класса является объект базового, ссылку или указатель на объект производного класса вполне можно преобразовать в ссылку или указатель на его доступный базовый класс.
При создании, копировании, перемещении и присвоении объектов производного класса сначала создается, копируется, перемещается и присваивается базовая часть объекта. Деструкторы выполняются в обратном порядке: сначала удаляется производная часть, затем выполняются деструкторы частей базовых классов. Базовые классы обычно определяют виртуальный деструктор, даже если у них нет никакой потребности в деструкторе.
Производный класс определяет уровень защиты для каждого из своих базовых классов. Члены открытого базового класса являются частью интерфейса производного класса; члены закрытого базового класса недоступны; члены защищенного базового класса доступны для классов, производных от него, но не для пользователей производного класса.
Термины
Абстрактный класс (abstract base class). Класс, обладающий одной или несколькими чистыми виртуальными функциями. Нельзя создать объекты типа абстрактного базового класса.