Стенли Липпман - Язык программирования C++. Пятое издание
- Название:Язык программирования C++. Пятое издание
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс
- Год:2014
- Город:Москва
- ISBN:978-5-8459-1839-0
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стенли Липпман - Язык программирования C++. Пятое издание краткое содержание
Вы держите в руках новое издание популярного и исчерпывающего бестселлера по языку программирования С++, которое было полностью пересмотрено и обновлено под
. Оно поможет вам быстро изучить язык и использовать его весьма эффективными и передовыми способами. В соответствии с самыми передовыми и современными методиками изложения материала авторы демонстрируют использование базового языка и его стандартной библиотеки для разработки эффективного, читабельного и мощного кода.
С самого начала этой книги читатель знакомится со стандартной библиотекой С++, ее самыми популярными функциями и средствами, что позволяет сразу же приступить к написанию полезных программ, еще не овладев всеми нюансами языка. Большинство примеров из книги было пересмотрено так, чтобы использовать новые средства языка и продемонстрировать их наилучшие способы применения. Эта книга — не только проверенное руководство для новичков в С++, она содержит также авторитетное обсуждение базовых концепций и методик языка С++ и является ценным ресурсом для опытных программистов, особенно желающих побыстрей узнать об усовершенствованиях С++11.
Стенли Б. Липпман Жози Лажойе Барбара Э. Му • Узнайте, как использовать новые средства языка С++11 и стандартной библиотеки для быстрого создания надежных программ, а также ознакомьтесь с высокоуровневым программированием
• Учитесь на примерах, в которых показаны передовые стили программирования и методики проектирования
• Изучите принципы и узнайте почему язык С++11 работает именно так
• Воспользуйтесь множеством перекрестных ссылок, способных помочь вам объединить взаимосвязанные концепции и проникнуть в суть
• Ознакомьтесь с современными методиками обучения и извлеките пользу из упражнений, в которых подчеркиваются ключевые моменты, позволяющие избежать проблем
• Освойте лучшие методики программирования и закрепите на практике изученный материал
Исходный код примеров можно загрузить с веб-страницы книги на сайте издательства по адресу: http://www.williamspublishing.com
Язык программирования C++. Пятое издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
class Screen {
public:
// другие члены интерфейса и реализации, как прежде
Screen& home(); // функции перемещения курсора
Screen& forward();
Screen& back();
Screen& up();
Screen& down();
};
Каждая из этих новых функций не получает никаких параметров и возвращает ссылку на вызвавший ее объект класса Screen
.
Можно определить функцию move()
, способную вызвать любую из этих функций и выполнить указанное действие. Для поддержки этой новой функции в класс Screen
добавлен статический член, являющийся массивом указателей на функции перемещения курсора:
class Screen {
public:
// другие члены интерфейса и реализации, как прежде
// Action - указатель, который может быть присвоен любой из
// функций-членов перемещения курсора
using Action = Screen&(Screen::*)();
// задать направление перемещения;
// перечисления описаны в разделе 19.3
enum Directions { HOME, FORWARD, BACK, UP, DOWN };
Screen& move(Directions);
private:
static Action Menu[]; // таблица функций
};
Массив Menu
содержит указатели на каждую из функций перемещения курсора. Эти функции будут храниться со смещениями, соответствующими перечислителям перечисления Directions
. Функция move()
получает перечислитель и вызывает соответствующую функцию:
Screen& Screen::move(Directions cm) {
// запустить элемент по индексу cm для объекта this
return (this->*Menu[cm])(); // Menu[cm] указывает на функцию-член
}
Вызов move()
обрабатывается следующим образом: выбирается элемент массива Menu
по индексу cm
. Этот элемент является указателем на функцию-член класса Screen
. Происходит вызов функции-члена, на которую указывает этот элемент от имени объекта, на который указывает указатель this
.
Когда происходит вызов функции move()
, ему передается перечислитель, указывающий направление перемещения курсора:
Screen myScreen;
myScreen.move(Screen::HOME); // вызывает myScreen.home
myScreen.move(Screen::DOWN); // вызывает myScreen.down
Остается только определить и инициализировать саму таблицу:
Screen::Action Screen::Menu[] = { &Screen::home,
&Screen::forward,
&Screen::back,
&Screen::up,
&Screen::down,
};
Упражнение 19.14. Корректен ли следующий код? Если да, то что он делает? Если нет, то почему?
auto pmf = &Screen::get_cursor; pmf = &Screen::get;
Упражнение 19.15. В чем разница между обычным указателем на функцию и указателем на функцию-член?
Упражнение 19.16. Напишите псевдоним типа, являющийся синонимом для указателя, способного указать на переменную-член avgprice
класса Sales_data
.
Упражнение 19.17. Определите псевдоним типа для каждого отдельного типа функции-члена класса Screen
.
19.4.3. Использование функций-членов как вызываемых объектов
Как уже упоминалось, для вызова через указатель на функцию-член, нужно использовать операторы .*
и ->*
для связи указателя с определенным объектом. В результате, в отличие от обычных указателей на функцию, указатель на функцию-член класса не является вызываемым объектом ; эти указатели не поддерживают оператор вызова функции (см. раздел 10.3.2).
Поскольку указатель на член класса не является вызываемым объектом, нельзя непосредственно передать указатель на функцию-член алгоритму. Например, если необходимо найти первую пустую строку в векторе строк, вполне очевидный вызов не сработает:
auto fp = &string::empty; // fp указывает на функцию empty()
// класса string
// ошибка: для вызова через указатель на член класса следует
// использовать оператор .* или ->*
find_if(svec.begin(), svec.end(), fp);
Алгоритм find_if()
ожидает вызываемый объект, но предоставляется указатель на функцию-член fp
. Этот вызов не будет откомпилирован, поскольку код в алгоритме find_if()
выполняет примерно такой оператор:
// проверяет применимость данного предиката к текущему элементу,
// возвращает true
if (fp(*it)) // ошибка: для вызова через указатель на член класса
// следует использовать оператор ->*
function
для создания вызываемого объектаОдин из способов получения вызываемого объекта из указателя на функцию-член подразумевает использование библиотечного шаблона function
(см. раздел 14.8.3):
function fcn = &string::empty;
find_if(svec.begin(), svec.end(), fcn);
Здесь шаблону function
указано, что empty()
— это функция, которая может быть вызвана со строкой и возвращает значение типа bool
. Обычно объект, для которого выполняется функция-член, передается неявному параметру this
. Когда шаблон function
используется при создании вызываемого объекта для функции-члена, следует преобразовать код так, чтобы сделать этот неявный параметр явным.
Когда объект шаблона function
содержит указатель на функцию-член, класс function
знает, что для вызова следует использовать соответствующий оператор указателя на член класса. Таким образом, можно предположить, что у функции find_if()
будет код наподобие следующего:
// если it является итератором в функции find_if(), то *it - объект
// в заданном диапазоне
if (fcn(*it)) // fcn - имя вызываемого объекта в функции find_if()
Его и выполнит шаблон класса function
, используя соответствующий оператор указателя на член класса. Класс function
преобразует этот вызов в такой код:
// если it является итератором в функции find_if(), то *it - объект
// в заданном диапазоне
if (((*it).*p)()) // p - указатель на функцию-член в функции fcn
При определении объекта шаблона function
следует указать тип функции, сигнатура которой определяет представляемые вызываемые объекты. Когда вызываемой объект является функцией-членом, первый параметр сигнатуры должен представить (обычно неявный) объект, для которого будет выполнена функция-член. Передаваемая шаблону function
сигнатура должна определять, будет ли объект передан как указатель или как ссылка.
При определении вызываемого объекта fcn()
было известно, что нужно вызвать функцию find_if()
для последовательности строковых объектов. Следовательно, от шаблона function
требовалось создать вызываемый объект, получающий объекты класса string
. Если бы вектор содержал указатели на тип string
, от шаблона function
требовалось бы ожидать указатель:
Интервал:
Закладка: