Стенли Липпман - Язык программирования C++. Пятое издание
- Название:Язык программирования C++. Пятое издание
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс
- Год:2014
- Город:Москва
- ISBN:978-5-8459-1839-0
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стенли Липпман - Язык программирования C++. Пятое издание краткое содержание
Вы держите в руках новое издание популярного и исчерпывающего бестселлера по языку программирования С++, которое было полностью пересмотрено и обновлено под
. Оно поможет вам быстро изучить язык и использовать его весьма эффективными и передовыми способами. В соответствии с самыми передовыми и современными методиками изложения материала авторы демонстрируют использование базового языка и его стандартной библиотеки для разработки эффективного, читабельного и мощного кода.
С самого начала этой книги читатель знакомится со стандартной библиотекой С++, ее самыми популярными функциями и средствами, что позволяет сразу же приступить к написанию полезных программ, еще не овладев всеми нюансами языка. Большинство примеров из книги было пересмотрено так, чтобы использовать новые средства языка и продемонстрировать их наилучшие способы применения. Эта книга — не только проверенное руководство для новичков в С++, она содержит также авторитетное обсуждение базовых концепций и методик языка С++ и является ценным ресурсом для опытных программистов, особенно желающих побыстрей узнать об усовершенствованиях С++11.
Стенли Б. Липпман Жози Лажойе Барбара Э. Му • Узнайте, как использовать новые средства языка С++11 и стандартной библиотеки для быстрого создания надежных программ, а также ознакомьтесь с высокоуровневым программированием
• Учитесь на примерах, в которых показаны передовые стили программирования и методики проектирования
• Изучите принципы и узнайте почему язык С++11 работает именно так
• Воспользуйтесь множеством перекрестных ссылок, способных помочь вам объединить взаимосвязанные концепции и проникнуть в суть
• Ознакомьтесь с современными методиками обучения и извлеките пользу из упражнений, в которых подчеркиваются ключевые моменты, позволяющие избежать проблем
• Освойте лучшие методики программирования и закрепите на практике изученный материал
Исходный код примеров можно загрузить с веб-страницы книги на сайте издательства по адресу: http://www.williamspublishing.com
Язык программирования C++. Пятое издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
На практике вполне очевидные случаи противоестественной перегрузки операторов довольно редки. Например, ни один ответственный программист не переопределил бы оператор operator+
для вычитания. Зато очень часто предпринимаются попытки неким образом приспособить "обычный" оператор, который неприменим к данному классу. Операторы следует использовать только для тех функций, которые будут однозначно поняты пользователями. Оператор с неоднозначным смыслом, например равенство, может быть интерпретирован по-разному.
Если класс обладает арифметическим (см. раздел 4.2) или побитовым (см. раздел 4.8) оператором, то его, как правило, имеет смысл снабдить соответствующими составными операторами. Вполне логично было бы также определить и оператор +=
. Само собой разумеется, оператор +=
должен быть определен так, чтобы он вел себя аналогично встроенным операторам, т.е. осуществлял составное присвоение: сначала сумма ( +
), а затем присвоение ( =
).
При проектировании перегруженных операторов необходимо принять решение, должен ли каждый из них быть членом класса или обычной функцией (не членом класса). В некоторых случаях выбора нет; оператор должен быть членом класса. В других случаях можно принять во внимание несколько эмпирических правил, которые помогут принять решение.
Приведенный ниже список критериев может оказаться полезен в ходе принятия решения о том, следует ли сделать оператор функцией-членом класса или обычной функцией.
• Операторы присвоения ( =
), индексирования ( []
), вызова ( ()
) и доступа к члену класса ( ->
) следует определять как функции-члены класса.
• Подобно оператору присвоения, составные операторы присвоения обычно должны быть членами класса. Но в отличие от оператора присвоения, это не обязательно.
• Другие операторы, которые изменяют состояние своего объекта или жестко связаны с данным классом (например, инкремент, декремент и обращение к значению), обычно должны быть членами класса.
• Симметричные операторы, такие как арифметические, операторы равенства, операторы сравнения и побитовые операторы, лучше определять как обычные функции, а не члены класса.
Разработчики ожидают возможности использовать симметричные операторы в выражениях со смешанными типами. Например, возможности сложить переменные типа int
и double
. Сложение симметрично, а потому можно использовать тип как левого, так и правого операнда.
Если необходимо обеспечить подобные выражения смешанного типа, задействующие объекты класса, то оператор должен быть определен как функция, не являющаяся членом класса.
При определении оператора как функции-члена левый операнд должен быть объектом того класса, членом которого является этот оператор. Например:
string s = "world";
string t = s + "!"; // ok: const char* можно добавить к строке
string u = "hi" + s; // возможна ошибка, если + будет членом
// класса string
Если бы оператор operator+ был членом класса string
, то первый случай сложения был бы эквивалентен s.operator+("!")
. Аналогично сложение "hi" + s
было бы эквивалентно "hi".operator+(s)
. Однако литерал "hi"
имеет тип const char*
, т.е. встроенный тип; у него нет функций-членов.
Поскольку класс string
определяет оператор +
как обычную функцию, не являющуюся членом класса, сложение "hi" + s
эквивалентно вызову operator+("hi", s)
. Подобно любому вызову функции, каждый из аргументов должен быть преобразуем в тип параметра. Единственное требование — по крайней мере один из операндов должен иметь тип класса, а оба операнда могут быть преобразованы в строку.
Упражнение 14.1. Чем перегруженный оператор отличается от встроенного? В чем перегруженные операторы совпадают со встроенными?
Упражнение 14.2. Напишите объявления для перегруженных операторов ввода, вывода, сложения и составного присвоения для класса Sales_data
.
Упражнение 14.3. Классы string
и vector
определяют перегруженный оператор ==
, применимый для сравнения объектов этих типов. Если векторы svec1
и svec2
содержат строки, объясните, какая из версий оператора ==
применяется в каждом из следующих выражений:
(a) "cobble" == "stone" (b) svec1[0] == svec2[0]
(c) svec1 == svec2 (d) "svec1[0] == "stone"
Упражнение 14.4. Объясните, должен ли каждый из следующих операторов быть членом класса и почему?
(а) % (b) %= (с) ++ (d) -> (е) << (f) && (g) == (h) ()
Упражнение 14.5. В упражнении 7.40 из раздела 7.5.1 был приведен набросок одного из следующих классов. Какой из перегруженных операторов должен (если должен) предоставить класс.
(a) Book (b) Date (с) Employee
(d) Vehicle (e) Object (f) Tree
14.2. Операторы ввода и вывода
Как уже упоминалось, библиотека IO использует операторы >>
и <<
для ввода и вывода соответственно. Сама библиотека IO определяет версии этих операторов для ввода и вывода данных встроенных типов. Классы, нуждающиеся во вводе и выводе, обычно определяют версии этих операторов для объектов данного класса.
14.2.1. Перегрузка оператора вывода
<<
Обычно первый параметр оператора вывода является ссылкой на неконстантный объект класса ostream
. Объект класса ostream
неконстантен потому, что запись в поток изменяет его состояние. Параметр является ссылкой потому, что нельзя копировать объект класса ostream
.
Второй параметр обычно должен быть ссылкой на константу типа класса, объект которого необходимо вывести. Параметр должен быть ссылкой во избежание копирования аргумента. Но он может быть константной ссылкой потому, что вывод объекта обычно не изменяет его.
Для совместимости с другими операторами вывода оператор operator<<
обычно возвращает свой параметр типа ostream
.
Sales_data
Для примера напишем оператор вывода для класса Sales_data
:
ostream &operator<<(ostream &os, const Sales_data &item) {
os << item.isbn() << " " << item.units_sold << " "
<< item.revenue << " " << item.avg_price();
return os;
}
За исключением имени эта функция идентична прежней версии функции print()
(см. раздел 7.1.3). Вывод объекта класса Sales_data
требует вывода значений всех его трех переменных-членов, а также вычисления средней цены (average price). Каждый элемент отделяется пробелом. После вывода значений оператор возвращает ссылку на использованный для этого объект класса ostream
.
Интервал:
Закладка: