Стенли Липпман - Язык программирования C++. Пятое издание
- Название:Язык программирования C++. Пятое издание
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс
- Год:2014
- Город:Москва
- ISBN:978-5-8459-1839-0
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стенли Липпман - Язык программирования C++. Пятое издание краткое содержание
Вы держите в руках новое издание популярного и исчерпывающего бестселлера по языку программирования С++, которое было полностью пересмотрено и обновлено под
. Оно поможет вам быстро изучить язык и использовать его весьма эффективными и передовыми способами. В соответствии с самыми передовыми и современными методиками изложения материала авторы демонстрируют использование базового языка и его стандартной библиотеки для разработки эффективного, читабельного и мощного кода.
С самого начала этой книги читатель знакомится со стандартной библиотекой С++, ее самыми популярными функциями и средствами, что позволяет сразу же приступить к написанию полезных программ, еще не овладев всеми нюансами языка. Большинство примеров из книги было пересмотрено так, чтобы использовать новые средства языка и продемонстрировать их наилучшие способы применения. Эта книга — не только проверенное руководство для новичков в С++, она содержит также авторитетное обсуждение базовых концепций и методик языка С++ и является ценным ресурсом для опытных программистов, особенно желающих побыстрей узнать об усовершенствованиях С++11.
Стенли Б. Липпман Жози Лажойе Барбара Э. Му • Узнайте, как использовать новые средства языка С++11 и стандартной библиотеки для быстрого создания надежных программ, а также ознакомьтесь с высокоуровневым программированием
• Учитесь на примерах, в которых показаны передовые стили программирования и методики проектирования
• Изучите принципы и узнайте почему язык С++11 работает именно так
• Воспользуйтесь множеством перекрестных ссылок, способных помочь вам объединить взаимосвязанные концепции и проникнуть в суть
• Ознакомьтесь с современными методиками обучения и извлеките пользу из упражнений, в которых подчеркиваются ключевые моменты, позволяющие избежать проблем
• Освойте лучшие методики программирования и закрепите на практике изученный материал
Исходный код примеров можно загрузить с веб-страницы книги на сайте издательства по адресу: http://www.williamspublishing.com
Язык программирования C++. Пятое издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
std::ostream &
operator<<(std::ostream &os, const Query &query) {
// Query::rep() осуществляет виртуальный вызов через свой
// указатель Query_base на rep()
return os << query.rep();
}
При выводе объекта класса Query
оператор вывода вызывает (открытую) функцию-член rep()
класса Query
. Эта функция осуществляет виртуальный вызов через свой указатель-член функции-члена rep()
объекта, на который указывает данный объект класса Query
.
Query andq = Query(sought1) & Query(sought2);
cout << andq << endl;
Таким образом, когда в коде встречается оператор вывода, он вызывает функцию Query::rep()
объекта andq
. Функция Query::rep()
в свою очередь осуществляет виртуальный вызов через свой указатель класса Query_base
на версию функции rep()
класса Query_base
. Поскольку объект andq
указывает на объект класса AndQuery
, этот вызов выполнит функцию AndQuery::rep()
.
Упражнение 15.32. Что будет при копировании, перемещении, присвоении и удалении объекта класса Query
?
Упражнение 15.33. А объектов класса Query_base
?
15.9.3. Производные классы
Самая интересная часть классов, производных от класса Query_base
, в том, как они представляются. Класс WordQuery
проще всех. Его задача — хранение искомого слова.
Другие классы работают на одном или двух операндах. У класса NotQuery
один операнд, а у классов AndQuery
и OrQuery
— по два. Операндами в каждом из этих классов могут быть объекты любого из реальных классов, производных от класса Query_base
: NotQuery
может быть применен к WordQuery
, как и AndQuery
, OrQuery
или NotQuery
. Для обеспечения такой гибкости операнды следует хранить как указатели на класс Query_base
. Таким образом, можно привязать указатель на любой необходимый реальный класс.
Но вместо того, чтобы хранить указатель на класс Query_base
, классы будут сами использовать объект Query
. Подобно тому, как пользовательский код упрощается при использовании класса интерфейса, можно упростить код собственного класса, используя тот же класс.
Теперь, когда конструкция этих классов известна, их можно реализовать.
WordQuery
Класс WordQuery
отвечает за поиск заданной строки. Это единственная операция, которая фактически выполняет запрос для данного объекта класса TextQuery
:
class WordQuery: public Query_base {
friend class Query; // Query использует конструктор WordQuery
WordQuery(const std::string &s) : query_word (s) { }
// конкретный класс: WordQuery определяет все унаследованные чистые
// виртуальные функции
QueryResult eval(const TextQuery &t) const
{ return t.query(query_word); }
std::string rep() const { return query_word; }
std::string query_word; // искомое слово
};
Подобно классу Query_base
, у класса WordQuery
нет открытых членов; он должен сделать класс Query
дружественным, чтобы позволить ему получать доступ к конструктору WordQuery()
.
Каждый из конкретных классов запроса должен определить унаследованные чистые виртуальные функции eval()
и rep()
. Обе функции определены в теле класса WordQuery
: функция eval()
вызывает функцию-член query()
своего параметра типа TextQuery
, который фактически осуществляет поиск в файле; функция rep()
возвращает строку, которую данный объект класса WordQuery
представляет (т.е. query_word
).
Определив класс WordQuery
, можно определить конструктор Query()
, получающий строку:
inline
Query::Query(const std::string &s): q(new WordQuery(s)) { }
Этот конструктор резервирует объект класса WordQuery
и инициализирует его указатель-член так, чтобы он указывал на этот недавно созданный объект.
NotQuery
и оператор ~
Оператор ~
подразумевает создание объекта класса NotQuery
, содержащего инверсный запрос:
class NotQuery: public Query_base {
friend Query operator~(const Query &);
NotQuery(const Query &q): query(q) { }
// конкретный класс: NotQuery определяет все унаследованные
// чистые виртуальные функции
std::string rep() const {return + query.rep() + ")";}
QueryResult eval(const TextQuery&) const;
Query query;
};
inline Query operator~(const Query &operand) {
return std::shared_ptr(new NotQuery(operand));
}
Поскольку все члены класса NotQuery
являются закрытыми, объявляем оператор ~
дружественным. Чтобы отобразить объект класса NotQuery
, следует вывести символ " ~
" сопровождаемый основным запросом. Чтобы сделать приоритет очевидным для читателя, заключим запрос в скобки.
Следует заметить то, что вызов функции rep()
объекта класса NotQuery
в конечном счете приводит к виртуальному вызову функции собственной функции-члена rep()
: query.rep()
— это невиртуальный вызов функции-члена rep()
класса Query
. Функция Query::rep()
в свою очередь осуществляет вызов q->rep()
, являющийся виртуальным вызовом через указатель Query_base
.
Оператор ~
динамически резервирует новый объект класса NotQuery
. Оператор return
(неявно) использует конструктор Query()
, получающий указатель shared_ptr
. Таким образом, оператор return
эквивалентен следующему:
// резервировать новый объект NotQuery
// связать новый объект NotQuery с указателем shared_ptr
shared_ptr tmp(new NotQuery(expr));
return Query(tmp); // использовать конструктор Query(), получающий
// указатель shared_ptr
Функция-член eval()
достаточно сложна, поэтому реализуем ее вне тела класса. Более подробно функция eval()
рассматривается в разделе 15.9.4.
BinaryQuery
Класс BinaryQuery
— это абстрактный базовый класс, содержащий данные, необходимые двум классам запроса, AndQuery
и OrQuery
, которые используют по два операнда:
class BinaryQuery: public Query_base {
protected:
BinaryQuery(const Query &l, const Query &r, std::string s):
lhs(l), rhs(r), opSym(s) { }
// абстрактный класс: BinaryQuery функцию eval() не определяет
std::string rep() const { return "(" + lhs.rep() + " "
+ opSym + " "
+ rhs.rep() + ")"; }
Query lhs, rhs; // правый и левый операнды
std::string opSym; // имя оператора
};
Данными класса BinaryQuery
являются два операнда запроса и символ оператора. Конструктор получает эти два операнда и символ оператора, каждый из которых он хранит в соответствующих переменных-членах.
Чтобы отобразить объект класса BinaryOperator
, следует вывести выражение в скобках, состоящее из левого операнда, оператора и правого операнда. Как и в случае класса NotQuery
, вызов функции rep()
в конечном счете осуществляет вызов виртуальных функций rep()
объектов класса Query_base
, на которые указывают параметры lhs
и rhs
.
Интервал:
Закладка: