- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Язык программирования C++. Пятое издание - Стенли Липпман
Шрифт:
Интервал:
Закладка:
find_if(svec.begin(), svec.end(), mem_fn(&string::empty));
Здесь шаблон mem_fn(&string::empty) создает вызываемый объект, получающий строковый аргумент и возвращающий логическое значение.
Вызываемый объект, созданный шаблоном mem_fn, может быть вызван для объекта или указателя:
auto f = mem_fn(&string::empty); // f получает string или string*
f(*svec.begin()); // ok: передача объекта string; f использует .* для
// вызова empty()
f(&svec[0]); // ok: передача указателя на string; f использует .->
// для вызова empty()
Фактически шаблон mem_fn можно считать как будто создающим вызываемый объект с перегруженным оператором вызова функции — один получает тип string*, а другой — string&.
Использование функции bind() для создания вызываемого объектаДля создания вызываемого объекта из функции-члена можно также использовать функцию bind() (см. раздел 10.3.4):
// связать каждую строку из диапазона
// с неявным первым аргументом empty()
auto it = find_if(svec.begin(), svec.end(),
bind(&string::empty, _1));
Подобно шаблону function, при использовании функции bind() следует сделать явным обычно неявный параметр функции-члена, представляющий объект, с которым будет работать функция-член. Подобно шаблону mem_fn, первый аргумент вызываемого объекта, создаваемого функцией bind(), может быть либо указателем, либо ссылкой на тип string:
auto f = bind(&string::empty, _1);
f(*svec.begin()); // ok: аргумент - строка f, использует .* для вызова
// функции empty()
f(&svec[0]); // ok: аргумент - указатель на строку f использует .->
// для вызова функции empty()
Упражнения раздела 19.4.3Упражнение 19.18. Напишите функцию, использующую алгоритм count_if() для подсчета количества пустых строк в заданном векторе.
Упражнение 19.19. Напишите функцию, получающую вектор vector<Sales_data> и находящую первый элемент, средняя цена которого превосходит заданное значение.
19.5. Вложенные классы
Класс, определяемый в другом классе, называется вложенным классом (nested class) или вложенным типом (nested type). Вложенные классы обычно используются для классов реализации, как, например, класс QueryResult из приложения текстового запроса (см. раздел 12.3).
Имя вложенного класса видимо в области видимости содержащего его класса, но не вне ее. Имя вложенного класса не будет входить в конфликт с тем же именем, объявленным в другой области видимости.
Вложенный класс может содержать члены тех же видов, что и не вложенный класс. Подобно любому другому классу, вложенный класс контролирует доступ к своим членам при помощи спецификаторов доступа. Содержащий класс не имеет никаких специальных прав доступа к членам вложенного класса, а вложенный класс не имеет привилегий в доступе к членам содержащего его класса.
В содержащем классе вложенный класс представляет собой член, типом которого является класс. Подобно любому другому члену, содержащий класс задает уровень доступа к этому типу. Вложенный класс, определенный в разделе public содержащего класса, может быть использован везде. Вложенный класс, определенный в разделе protected, доступен только содержащему классу, его производным и дружественным классам. Вложенный класс, определенный в разделе private, доступен лишь для членов содержащего класса и классов, дружественных для него.
Объявление вложенного классаКласс TextQuery из раздела 12.3.2 определял сопутствующий класс QueryResult. Класс QueryResult жестко связан с классом TextQuery. Класс QueryResult имело бы смысл использовать и для других целей, а не только для результатов операции запроса к объекту класса TextQuery. Для отражения этой жесткой связи сделаем класс QueryResult членом класса TextQuery.
class TextQuery {
public:
class QueryResult; // вложенный класс будет определен позже
// другие члены, как в разделе 12.3.2
};
В первоначальный класс TextQuery необходимо внести только одно изменение — объявить о намерении определить класс QueryResult как вложенный. Поскольку класс QueryResult будет типом-членом (см. раздел 7.3.4), его следует объявить прежде, чем использовать. В частности, класс QueryResult следует объявить прежде, чем использовать его как тип возвращаемого значения функции-члена query(). Остальные члены первоначального класса неизменны.
Определение вложенного класса вне содержащего классаВ классе TextQuery класс QueryResult объявлен, но не определен. Подобно функциям-членам, вложенные классы следует объявить в классе, но определен он может быть в или вне класса.
При определении вложенного класса вне его содержащего класса следует квалифицировать имя вложенного класса именем его содержащего класса:
// определение класса QueryResult как члена класса TextQuery
class TextQuery::QueryResult {
// в области видимости класса не нужно квалифицировать имя
// параметров QueryResult
friend std::ostream&
print(std::ostream&, const QueryResult&);
public:
// не нужно определять QueryResult::line_no; вложенный класс способен
// использовать член своего содержащего класса без необходимости
// квалифицировать его имя
QueryResult(std::string,
std::shared_ptr<std::set<line_no>>,
std::shared_ptr<std::vector<std::string>>);
// другие члены, как в разделе 12.3.2
};
Единственное изменение, внесенное в первоначальный класс, заключается в том, что в классе QueryResult больше не определяется переменная-член line_no. Члены класса QueryResult могут обращаться к этому имени непосредственно в классе TextQuery, таким образом, нет никакой необходимости определять его снова.
Пока не встретится фактическое определение вложенного класса, расположенное вне тела класса, этот класс является незавершенным типом (см. раздел 7.3.3).
Определение членов вложенного классаВ этой версии конструктор QueryResult() не определяется в теле класса. Чтобы определить конструктор, следует указать, что класс QueryResult вложен в пределы класса TextQuery. Для этого имя вложенного класса квалифицируют именем содержащего его класса:
// определение члена класса по имени QueryResult для класса по
// имени QueryResult, вложенного в класс TextQuery
TextQuery::QueryResult::QueryResult(string s,
shared_ptr<set<line_no>> p,
shared_ptr<vector<string>> f):
sought(s), lines (p), file(f) { }
Читая имя функции справа налево, можно заметить, что это определение конструктора для класса QueryResult, который вложен в пределы класса TextQuery. Сам код только сохраняет данные аргументов в переменных-членах и не делает больше ничего.
Определение статических членов вложенных классовЕсли бы класс QueryResult объявлял статический член, его определение находилось бы вне области видимости класса TextQuery. Например, статический член класса QueryResult был бы определен как-то так:
// определение статического члена типа int класса QueryResult
// вложенного в класс TextQuery
int TextQuery::QueryResult::static_mem = 1024;
Поиск имен в области видимости вложенного классаВо вложенном классе выполняются обычные правила поиска имен (см. раздел 7.4.1). Конечно, поскольку вложенный класс — это вложенная область видимости, для поиска у него есть дополнительные области видимости в содержащем классе. Такое вложение областей видимости объясняет, почему переменная-член line_no не определялась во вложенной версии класса QueryResult. Первоначальный класс QueryResult определял этот член для того, чтобы его собственные члены могли избежать необходимости записи TextQuery::line_no. После вложения определения класса результатов в класс TextQuery такое определение типа больше не нужно. Вложенный класс QueryResult может обратиться к переменной line_no без указания, что она определена в классе TextQuery.
Как уже упоминалось, вложенный класс — это тип-член содержащего его класса. Члены содержащего класса могут использовать имена вложенного класса таким же образом, как и любой другой тип-член. Поскольку класс QueryResult вложен в класс TextQuery, функция-член query() класса TextQuery может обращаться к имени QueryResult непосредственно:

