Стенли Липпман - Язык программирования C++. Пятое издание
- Название:Язык программирования C++. Пятое издание
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс
- Год:2014
- Город:Москва
- ISBN:978-5-8459-1839-0
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стенли Липпман - Язык программирования C++. Пятое издание краткое содержание
Вы держите в руках новое издание популярного и исчерпывающего бестселлера по языку программирования С++, которое было полностью пересмотрено и обновлено под
. Оно поможет вам быстро изучить язык и использовать его весьма эффективными и передовыми способами. В соответствии с самыми передовыми и современными методиками изложения материала авторы демонстрируют использование базового языка и его стандартной библиотеки для разработки эффективного, читабельного и мощного кода.
С самого начала этой книги читатель знакомится со стандартной библиотекой С++, ее самыми популярными функциями и средствами, что позволяет сразу же приступить к написанию полезных программ, еще не овладев всеми нюансами языка. Большинство примеров из книги было пересмотрено так, чтобы использовать новые средства языка и продемонстрировать их наилучшие способы применения. Эта книга — не только проверенное руководство для новичков в С++, она содержит также авторитетное обсуждение базовых концепций и методик языка С++ и является ценным ресурсом для опытных программистов, особенно желающих побыстрей узнать об усовершенствованиях С++11.
Стенли Б. Липпман Жози Лажойе Барбара Э. Му • Узнайте, как использовать новые средства языка С++11 и стандартной библиотеки для быстрого создания надежных программ, а также ознакомьтесь с высокоуровневым программированием
• Учитесь на примерах, в которых показаны передовые стили программирования и методики проектирования
• Изучите принципы и узнайте почему язык С++11 работает именно так
• Воспользуйтесь множеством перекрестных ссылок, способных помочь вам объединить взаимосвязанные концепции и проникнуть в суть
• Ознакомьтесь с современными методиками обучения и извлеките пользу из упражнений, в которых подчеркиваются ключевые моменты, позволяющие избежать проблем
• Освойте лучшие методики программирования и закрепите на практике изученный материал
Исходный код примеров можно загрузить с веб-страницы книги на сайте издательства по адресу: http://www.williamspublishing.com
Язык программирования C++. Пятое издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
// каждая пара объявляет ту же функцию
Record lookup(const Account &acct);
Record lookup(const Account&); // имена параметров игнорируются
typedef Phone Telno;
Record lookup(const Phone&);
Record lookup(const Telno&); // Telno и Phone того же типа
Первое объявление в первой паре именует свой параметр. Имена параметров предназначены только для документирования. Они не изменяют список параметров.
Во второй паре типы только выглядят разными, Telno
— не новый тип, это только синоним типа Phone
. Псевдоним типа (см. раздел 2.5.1) предоставляет альтернативное имя для уже существующего типа, а не создает новый тип. Поэтому два параметра, отличающиеся только тем, что один использует имя типа, а другой его псевдоним, не являются разными.

Как упоминалось в разделе 6.2.3, спецификатор const
верхнего уровня (см. раздел 2.4.3) никак не влияет на объекты, которые могут быть переданы функции. Параметр, у которого есть спецификатор const
верхнего уровня, неотличим от такового без спецификатора const
верхнего уровня:
Record lookup(Phone);
Record lookup(const Phone); // повторно объявляет Record lookup(Phone)
Record lookup(Phone*);
Record lookup(Phone* const); // повторно объявляет
// Record lookup(Phone*)
Здесь вторые объявления повторно объявляет ту же функцию, что и первые. С другой стороны, функцию можно перегрузить на основании того, является ли параметр ссылкой (или указателем) на константную или неконстантную версию того же типа; речь идет о спецификаторе const
нижнего уровня:
// функции, получающие константную и неконстантную ссылку (или
// указатель), имеют разные параметры
Record lookup(Account&); // функция получает ссылку на Account
Record lookup(const Account&); // новая функция получает константную
// ссылку
Record lookup(Account*); // новая функция получает указатель
// на Account
Record lookup(const Account*); // новая функция получает указатель на
// константу
В этих случаях компилятор может использовать константность аргумента, чтобы различить, какую функцию применять. Поскольку нет преобразования (см. раздел 4.11.2) из константы, можно передать константный объект (или указатель на константу) только версии с константным параметром. Так как преобразование в константу возможно, можно вызвать функцию и неконстантного объекта, и указателя на неконстантный объект. Однако, как будет представлено в разделе 6.6.1, компилятор предпочтет неконстантные версии при передаче неконстантного объекта или указателя на неконстантный объект.
Хотя перегрузка функций позволяет избежать необходимости создавать и запоминать имена общепринятых операций, она не всегда целесообразна. В некоторых случаях разные имена функций предоставляют дополнительную информацию, которая упрощает понимание программы. Давайте рассмотрим набор функций-членов класса Screen
, отвечающих за перемещение курсора.
Screen& moveHome();
Screen& moveAbs(int, int);
Screen& moveRel(int, int, string direction);
На первый взгляд может показаться, что этот набор функций имеет смысл перегрузить под именем move
:
Screen& move();
Screen& move(int, int);
Screen& move(int, int, string direction);
Однако при перегрузке этих функций мы потеряли информацию, которая была унаследована именами функции. Хотя перемещение курсора — это общая операция, совместно используемая всеми этими функциями, специфический характер перемещения уникален для каждой из этих функций. Рассмотрим, например, функцию moveHome()
, осуществляющую вполне определенное перемещение курсора. Какое из двух приведенных ниже обращений понятнее при чтении кода?
// которая из записей понятней?
myScreen.moveHome(); // вероятно, эта!
myScreen.move();
const_cast
и перегрузкаВ разделе 4.11.3 упоминалось, что оператор const_cast
особенно полезен в контексте перегруженных функций. В качестве примера вернемся к функции shorterString()
из раздела 6.3.2:
// возвратить ссылку на строку, которая короче
const string &shorterString (const string &s1, const string &s2) {
return s1.size() <= s2.size() ? s1 : s2;
}
Эта функция получает и возвращает ссылки на константную строку. Мы можем вызвать функцию с двумя неконстантными строковыми аргументами, но как результат получим ссылку на константную строку. Могла бы понадобиться версия функции shorterString()
, которая, получив неконстантные аргументы, возвратит обычную ссылку. Мы можем написать эту версию функции, используя оператор const_cast
:
string &shorterString(string &s1, string &s2) {
auto &r = shorterString(const_cast(s1),
const_cast(s2));
return const_cast(r);
}
Эта версия вызывает константную версию функции shorterString()
при приведении типов ее аргументов к ссылкам на константу. Функция возвращает ссылку на тип const string
, которая, как известно, привязана к одному из исходных, неконстантных аргументов. Следовательно, приведение этой строки назад к обычной ссылке string&
при возвращении вполне безопасно.
Когда набор перегруженных функций определен, необходима возможность вызвать их с соответствующими аргументами. Подбор функции (function matching), известный также как поиск перегруженной функции (overload resolution), — это процесс, в ходе которого вызов функции ассоциируется с определенной версией из набора перегруженных функций. Компилятор определяет, какую именно версию функции использовать при вызове, сравнивая аргументы вызова с параметрами каждой функции в наборе.
Как правило, вовсе несложно выяснить, допустим ли вызов, и если он допустим, то какая из версий функции будет использована компилятором. Функции в наборе перегруженных версий отличаются количеством или типом аргументов. В таких случаях определить используемую функцию просто. Подбор функции усложняется в случае, когда количество параметров одинаково и они допускают преобразование (см. раздел 4.11) переданных аргументов. Распознавание вызовов компилятором при наличии преобразований рассматривается в разделе 6.6, а пока следует понять, что при любом вызове перегруженной функции возможен один из трех результатов.
• Компилятор находит одну функцию, которая является наилучшим соответствием (best match) для фактических аргументов, и создает код ее вызова.
• Компилятор не может найти ни одной функции, параметры которой соответствуют аргументам вызова. В этом случае компилятор сообщает об ошибке отсутствия соответствия (no match).
Читать дальшеИнтервал:
Закладка: