- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп
Шрифт:
Интервал:
Закладка:
Month mm = Month(7); // преобразование типа int в тип Month
//(без проверки)
Обратите внимание на то, что Month — это отдельный тип. Он может быть неявно преобразован в тип int, но неявного преобразования типа Month в тип int не существует. Это имеет смысл, поскольку каждый объект класса Month имеет эквивалентное целое значение, но большинство целых чисел не имеет эквивалентного значения типа Month. Например, мы преднамеренно написали неправильную инициализацию.
Month bad = 9999; // ошибка: целое число невозможно преобразовать
// объект типа Month
Если вы настаиваете на использовании обозначения Month(9999), то сами будете виноваты! Во многих ситуациях язык С++ не пытается останавливать программиста от потенциально опасных действий, если программист явно на этом настаивает; в конце концов, программисту, действительно, виднее.
К сожалению, мы не можем определить конструктор для перечисления, чтобы проверить начальные значения, но написать простую функцию для проверки не составляет труда.
Month int_to_month(int x)
{
if (x<jan || dec<x) error("неправильный месяц");
return Month(x);
}
Теперь можно написать следующий код:
void f(int m)
{
Month mm = int_to_month(m);
// ...
}
Для чего нужны перечисления? В основном перечисление полезно, когда нам нужно множество связанных друг с другом именованных целочисленных констант. Как правило, с помощью перечислений представляют наборы альтернатив (up, down; yes, no, maybe; on, off; n, ne, e, se, s, sw, w, nw) или отличительных признаков (red, blue, green, yellow, maroon, crimson, black).
Обратите внимание на то, что элементы перечисления не входят в отдельную область видимости своего перечисления; они находятся в той же самой области видимости, что и имя их перечисления. Рассмотрим пример.
enum Traffic_sign { red, yellow, green };
int var = red; // примечание: правильно Traffic_sign::red
Этот код вызывает проблемы. Представьте себе, что в вашей программе в качестве глобальных используются такие распространенные имена, как red, on, ne и dec. Например, что значит ne: “северо-восток” (northeast) или “не равно” (nor equal)? Что значит dec: “десятичный” (decimal) или “декабрь” (December)? Именно о таким проблемах мы предупреждали в разделе 3.7. Они легко возникнут, если определить перечисление с короткими и общепринятыми именами элементов в глобальном пространстве имен. Фактически мы сразу сталкиваемся с этой проблемой, когда пытаемся использовать перечисление Month вместе с потоками iostream, поскольку для десятичных чисел существует манипулятор с именем dec (см. раздел 11.2.1). Для того чтобы избежать возникновения этих проблем, мы часто предпочитаем определять перечисления в более ограниченных областях видимости, например в классе. Это также позволяет нам явно указать, на что ссылаются значения элементов перечисления, такие как Month::jan и Color::red. Приемы работы с перечислениями описываются в разделе 9.7.1. Если нам очень нужны глобальные имена, то необходимо минимизировать вероятность коллизий, используя более длинные или необычные имена, а также прописные буквы. Тем не менее мы считаем более разумным использовать имена перечислений в локальных областях видимости.
9.6. Перегрузка операторов
Для класса или перечисления можно определить практически все операторы, существующие в языке С++. Этот процесс называют перегрузкой операторов (operator overloading). Он применяется, когда требуется сохранить привычные обозначения для разрабатываемого нами типа. Рассмотрим пример.
enum Month {
Jan=1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec
};
Month operator++(Month& m) // префиксный инкрементный оператор
{
m = (m==Dec) ? Jan : Month(m+1); // "циклический переход"
return m;
}
Конструкция ? : представляет собой арифметический оператор “если”: переменная m становится равной Jan, если (m==Dec), и Month(m+1) в противном случае. Это довольно элегантный способ, отражающий цикличность календаря. Тип Month теперь можно написать следующим образом:
Month m = Sep;
++m; // m становится равным Oct
++m; // m становится равным Nov
++m; // m становится равным Dec
++m; // m становится равным Jan ("циклический переход")
Можно не соглашаться с тем, что инкрементация перечисления Month является широко распространенным способом, заслуживающим реализации в виде отдельного оператора. Однако что вы скажете об операторе вывода? Его можно описать так:
vector<string> month_tbl;
ostream& operator<<(ostream& os, Month m)
{
return os << month_tbl[m];
}
Это значит, что объект month_tbl был инициализирован где-то, так что, например, month_tbl[Mar] представляет собой строку "March" или какое-то другое подходящее название месяца (см. раздел 10.11.3).
Разрабатывая собственный тип, можно перегрузить практически любой оператор, предусмотренный в языке С++, например +, –, *, /, %, [], (), ^, !, &, <, <=, > и >=. Невозможно определить свой собственный оператор; можно себе представить, что программист захочет иметь операторы ** или $=, но язык С++ этого не допускает. Операторы можно определить только для установленного количества операндов; например, можно определить унарный оператор –, но невозможно перегрузить как унарный оператор <= (“меньше или равно”). Аналогично можно перегрузить бинарный оператор +, но нельзя перегрузить оператор ! (“нет”) как бинарный. Итак, язык позволяет использовать для определенных программистом типов существующие синтаксические выражения, но не позволяет расширять этот синтаксис.
Перегруженный оператор должен иметь хотя бы один операнд, имеющий тип, определенный пользователем.
int operator+(int,int); // ошибка: нельзя перегрузить встроенный
// оператор +
Vector operator+(const Vector&, const Vector &); // OK
Vector operator+=(const Vector&, int); // OK
Мы рекомендуем не определять оператор для типа, если вы не уверены полностью, что это значительно улучшит ваш код. Кроме того, операторы следует определять, сохраняя их общепринятый смысл: оператор + должен обозначать сложение; бинарный оператор * — умножение; оператор [] — доступ; оператор () — вызов функции и т.д. Это просто совет, а не

