Стенли Липпман - Язык программирования C++. Пятое издание
- Название:Язык программирования C++. Пятое издание
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс
- Год:2014
- Город:Москва
- ISBN:978-5-8459-1839-0
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стенли Липпман - Язык программирования C++. Пятое издание краткое содержание
Вы держите в руках новое издание популярного и исчерпывающего бестселлера по языку программирования С++, которое было полностью пересмотрено и обновлено под
. Оно поможет вам быстро изучить язык и использовать его весьма эффективными и передовыми способами. В соответствии с самыми передовыми и современными методиками изложения материала авторы демонстрируют использование базового языка и его стандартной библиотеки для разработки эффективного, читабельного и мощного кода.
С самого начала этой книги читатель знакомится со стандартной библиотекой С++, ее самыми популярными функциями и средствами, что позволяет сразу же приступить к написанию полезных программ, еще не овладев всеми нюансами языка. Большинство примеров из книги было пересмотрено так, чтобы использовать новые средства языка и продемонстрировать их наилучшие способы применения. Эта книга — не только проверенное руководство для новичков в С++, она содержит также авторитетное обсуждение базовых концепций и методик языка С++ и является ценным ресурсом для опытных программистов, особенно желающих побыстрей узнать об усовершенствованиях С++11.
Стенли Б. Липпман Жози Лажойе Барбара Э. Му • Узнайте, как использовать новые средства языка С++11 и стандартной библиотеки для быстрого создания надежных программ, а также ознакомьтесь с высокоуровневым программированием
• Учитесь на примерах, в которых показаны передовые стили программирования и методики проектирования
• Изучите принципы и узнайте почему язык С++11 работает именно так
• Воспользуйтесь множеством перекрестных ссылок, способных помочь вам объединить взаимосвязанные концепции и проникнуть в суть
• Ознакомьтесь с современными методиками обучения и извлеките пользу из упражнений, в которых подчеркиваются ключевые моменты, позволяющие избежать проблем
• Освойте лучшие методики программирования и закрепите на практике изученный материал
Исходный код примеров можно загрузить с веб-страницы книги на сайте издательства по адресу: http://www.williamspublishing.com
Язык программирования C++. Пятое издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
// возвращает пересечение наборов результатов своих операндов
QueryResult
AndQuery::eval(const TextQuery& text) const {
// виртуальный вызов через операнды класса Query для получения
// результирующих наборов для операндов
auto left = lhs.eval(text), right = rhs.eval(text);
// набор для хранения пересечения left и right
auto ret_lines = make_shared>();
// выводит пересечение двух диапазонов в итератор назначения
// итератор назначения в этом вызове добавляет элементы в 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>();
// следует перебрать строки, в которых присутствует операнд
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.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) Позвольте пользователю ограничивать результаты так, чтобы отображался набор соответствий только в заданном диапазоне строк.
Резюме
Наследование позволяет создавать новые классы, которые совместно используют возможности их базового класса (классов), но при необходимости могут их переопределить или дополнить. Динамическое связывание позволяет компилятору во время выполнения выбрать версию применяемой функции на основании динамического типа объекта. Комбинация наследования и динамического связывания позволяет создавать программы, которые либо не зависят от типа объекта, либо имеют поведение, зависящие от типа объекта.
В языке С++ динамическое связывание применимо только к тем функциям, которые объявлены виртуальными и вызываются при помощи ссылок или указателей.
Объекты производных классов состоят из части (частей) базового класса и части производного. Поскольку частью объекта производного класса является объект базового, ссылку или указатель на объект производного класса вполне можно преобразовать в ссылку или указатель на его доступный базовый класс.
При создании, копировании, перемещении и присвоении объектов производного класса сначала создается, копируется, перемещается и присваивается базовая часть объекта. Деструкторы выполняются в обратном порядке: сначала удаляется производная часть, затем выполняются деструкторы частей базовых классов. Базовые классы обычно определяют виртуальный деструктор, даже если у них нет никакой потребности в деструкторе.
Читать дальшеИнтервал:
Закладка: