Стенли Липпман - Язык программирования C++. Пятое издание
- Название:Язык программирования C++. Пятое издание
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс
- Год:2014
- Город:Москва
- ISBN:978-5-8459-1839-0
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стенли Липпман - Язык программирования C++. Пятое издание краткое содержание
Вы держите в руках новое издание популярного и исчерпывающего бестселлера по языку программирования С++, которое было полностью пересмотрено и обновлено под
. Оно поможет вам быстро изучить язык и использовать его весьма эффективными и передовыми способами. В соответствии с самыми передовыми и современными методиками изложения материала авторы демонстрируют использование базового языка и его стандартной библиотеки для разработки эффективного, читабельного и мощного кода.
С самого начала этой книги читатель знакомится со стандартной библиотекой С++, ее самыми популярными функциями и средствами, что позволяет сразу же приступить к написанию полезных программ, еще не овладев всеми нюансами языка. Большинство примеров из книги было пересмотрено так, чтобы использовать новые средства языка и продемонстрировать их наилучшие способы применения. Эта книга — не только проверенное руководство для новичков в С++, она содержит также авторитетное обсуждение базовых концепций и методик языка С++ и является ценным ресурсом для опытных программистов, особенно желающих побыстрей узнать об усовершенствованиях С++11.
Стенли Б. Липпман Жози Лажойе Барбара Э. Му • Узнайте, как использовать новые средства языка С++11 и стандартной библиотеки для быстрого создания надежных программ, а также ознакомьтесь с высокоуровневым программированием
• Учитесь на примерах, в которых показаны передовые стили программирования и методики проектирования
• Изучите принципы и узнайте почему язык С++11 работает именно так
• Воспользуйтесь множеством перекрестных ссылок, способных помочь вам объединить взаимосвязанные концепции и проникнуть в суть
• Ознакомьтесь с современными методиками обучения и извлеките пользу из упражнений, в которых подчеркиваются ключевые моменты, позволяющие избежать проблем
• Освойте лучшие методики программирования и закрепите на практике изученный материал
Исходный код примеров можно загрузить с веб-страницы книги на сайте издательства по адресу: http://www.williamspublishing.com
Язык программирования C++. Пятое издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
}
Хоть и не обязательно делать это, вполне допустимо указать ключевое слово inline
и в объявлении, и в определении. Однако указание ключевого слова inline
в определении только вне класса может облегчить чтение класса.
По тем же причинам, по которым встраиваемые функции определяют в заголовках (см. раздел 6.5.2), встраиваемые функции-члены следует определить в том же заголовке, что и определение соответствующего класса.
Подобно функциям, которые не являются членами класса, функции-члены могут быть перегружены (см. раздел 6.4), если они отличаются количеством и/или типами параметров. При вызове функции-члена используется тот же процесс подбора функции (см. раздел 6.4), что и у функций, не являющихся членом класса.
Например, в классе Screen
определены две версии функции get()
. Одна версия возвращает символ, обозначенный в настоящее время курсором; другая возвращает символ в указанной позиции, определенной ее рядом и столбцом. Чтобы определить применяемую версию, компилятор использует количество аргументов:
Screen myscreen;
char ch = myscreen.get(); // вызов Screen::get()
ch = myscreen.get(0,0); // вызов Screen::get(pos, pos)
Иногда (но не очень часто) у класса есть переменная-член, которую следует сделать изменяемой даже в константной функции-члене. Для обозначения таких членов в их объявление включают ключевое слово mutable
.
Изменяемая переменная-член (mutable data member) никогда не бывает константой, даже когда это член константного объекта. Соответственно константная функция-член может изменить изменяемую переменную-член. В качестве примера добавим в класс Screen
изменяемую переменную-член access_ctr
, используемую для отслеживания частоты вызова каждой функции-члена класса Screen
:
class Screen {
public:
void some_member() const;
private:
mutable size_t access_ctr; // может измениться даже в константном
// объекте
// другие члены как прежде
};
void Screen::some_member() const {
++access_ctr; // сохранить количество вызовов любой функции-члена
// безотносительно других выполняемых ею действий
}
Несмотря на то что функция-член some_member()
константная, она может изменить значение переменной-члена access_сtr
. Этот член класса является изменяемым, поэтому любая функция-член, включая константные, может изменить это значение.
Кроме класса
Screen
, определим также класс диспетчера окон, который представляет коллекцию окон на данном экране. У этого класса будет вектор объектов класса Screen
, каждый элемент которого представляет отдельное окно. По умолчанию класс Window_mgr
должен изначально содержать один объект класса Screen
, инициализированный значением по умолчанию. По новому стандарту наилучшим способом определения такого значения по умолчанию является внутриклассовый инициализатор (см. раздел 2.6.1):
class Window_mgr {
private:
// по умолчанию отслеживающий окна объект класса Window_mgr
// содержит одно пустое окно стандартного размера
std::vector screens{Screen(24, 80, ' ')};
};
При инициализации переменных-членов типа класса их конструктору следует предоставить аргументы. В этом случае применяется список инициализации переменной-члена типа vector
(см. раздел 3.3.1) с инициализатором для одного элемента. Этот инициализатор содержит значение типа Screen
, передаваемое конструктору vector
для создания вектора с одним элементом. Это значение создается конструктором класса Screen
, получающим параметры в виде двух размерностей и заполняющего символа, чтобы создать пустое окно заданного размера.
Как уже упоминалось, для внутриклассовой инициализации может использоваться форма инициализации =
(как при инициализации переменных-членов класса Screen
) или прямая форма инициализации с использованием фигурных скобок (как у вектора screens
).
При предоставлении внутриклассового инициализатора это следует сделать после знака
=
или в фигурных скобках.
Упражнение 7.23. Напишите собственную версию класса Screen
.
Упражнение 7.24. Добавьте в свой класс Screen
три конструктора: стандартный; получающий высоту, ширину и заполняющий содержимое соответствующим количеством пробелов; получающий высоту, ширину и заполняющий символ для содержимого экрана.
Упражнение 7.25. Может ли класс Screen
безопасно полагаться на заданные по умолчанию версии операторов копирования и присвоения? Если да, то почему? Если нет, то почему?
Упражнение 7.26. Определите функцию Sales data::avg_price
как встраиваемую.
7.3.2. Функции, возвращающие указатель
*this
Теперь добавим функции, устанавливающие символ в курсоре или в заданной области:
class Screen {
public:
Screen &set(char);
Screen &set(pos, pos, char);
// другие члены, как прежде
};
inline Screen &Screen::set(char c) {
contents[cursor] = с; // установите новое значение в текущей позиции
// курсора
return *this; // возвратить этот объект как l-значение
}
inline Screen &Screen::set(pos r, pos col, char ch) {
contents[r * width + col] = ch; // установить позицию по данному
// значению
return *this; // возвратить этот объект как l-значение
}
Как и функция move()
, функция-член set()
возвращает ссылку на объект, из которого они вызваны (см. раздел 7.1.2). Возвращающие ссылку функции являются l-значениями (см. раздел 6.3.2), а это означает, что они возвращают сам объект, а не его копию. Это позволяет связать несколько их вызовов в одно выражение:
// переместить курсор в указанную позицию и присвоить
// символу значение
myScreen.move(4,0).set('#');
Эти операции выполнятся для того же объекта. В этом выражении сначала перемещается курсор ( move()
) в окно ( myScreen
), а затем устанавливается ( set()
) заданный символ. Таким образом, этот оператор эквивалентен следующему:
myScreen.move(4,0);
myScreen.set('#');
Если бы функции move()
и set()
возвращали тип Screen
, а не Screen&
, этот оператор выполнялся бы совсем по-другому. В данном случае он был бы эквивалентен следующему:
Интервал:
Закладка: