- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Язык программирования C++. Пятое издание - Стенли Липпман
Шрифт:
Интервал:
Закладка:
Поскольку перегруженные версии этих операторов не сохраняют порядок вычисления и (или) не поддерживают вычисления по сокращенной схеме, их перегрузка обычно — плохая идея. Пользователи, вероятно, будут удивлены отсутствием привычных гарантий последовательности вычисления в коде при использовании перегруженной версии одного из этих операторов.
Еще один повод не перегружать операторы запятой и обращения к адресу заключается в том, что, в отличие от большинства операторов, язык сам определяет значение этих операторов, когда они применены к объектам типа класса. Поскольку у этих операторов есть встроенное значение, они обычно не должны перегружаться. Пользователи класса будут удивлены, если они поведут себя не так, как обычно.
Обычно операторы запятая, обращение к адресу, логический оператор AND и OR не должны быть перегружены.
Использование определений, совместимых со встроенным смысломПри разработке класса всегда следует сначала подумать об обеспечиваемых им операциях. Только определившись с необходимыми операциями, следует подумать о том, стоит ли определить некую операцию как обычную функцию или как перегруженный оператор. Те операции, которые логически соответствуют операторам, — это хорошие кандидаты на определение в качестве перегруженных операторов.
• Если класс осуществляет операции ввода и вывода, имеет смысл определить операторы сдвига для совместимости с таковыми у встроенных типов.
• Если класс подразумевает проверку на равенство, определите оператор operator==. Если у класса есть оператор operator==, то у него обычно должен быть также оператор operator!=.
• Если у класса должна быть операция упорядочивания, определите оператор operator< Если у класса есть оператор operator<, то у него, вероятно, должны быть все операторы сравнения.
• Тип возвращаемого значения перегруженного оператора обычно должен быть совместимым с таковым у встроенной версии оператора: логические операторы и операторы отношения должны возвращать значение типа bool, арифметические операторы должны возвращать значение типа класса, операторы присвоения и составные операторы присвоения должны возвращать ссылку на левый операнд.
Составные операторы присвоенияОператоры присвоения должны вести себя аналогично синтезируемым операторам: после присвоения значения левых и правых операндов должны быть одинаковы, а возвратить оператор должен ссылку на левый операнд. Перегруженный оператор присвоения должен обобщить смысл встроенного оператора присвоения, а не переиначивать его.
Внимание! Будьте осторожны при использовании перегруженных операторовКаждый оператор имеет некий смысл, когда он используется для встроенных типов. Бинарный оператор +, например, всегда означает сумму. Вполне логично и удобно применять в классе бинарный оператор + для аналогичной функции. Например, библиотечный тип string, в соответствии с соглашением, общепринятым для множества языков программирования, использует оператор + для конкатенации, т.е. добавления содержимого одной строки в другую.
Перегруженные операторы полезней всего тогда, когда смысл встроенного оператора логически соответствует функции текущего класса. Применение перегруженных операторов вместо именованных функций позволяет сделать программы более простыми, естественными и интуитивно понятными. Злоупотребление перегруженными операторами, а также придание не свойственного им смысла сделает класс неудобным в применении.
На практике вполне очевидные случаи противоестественной перегрузки операторов довольно редки. Например, ни один ответственный программист не переопределил бы оператор operator+ для вычитания. Зато очень часто предпринимаются попытки неким образом приспособить "обычный" оператор, который неприменим к данному классу. Операторы следует использовать только для тех функций, которые будут однозначно поняты пользователями. Оператор с неоднозначным смыслом, например равенство, может быть интерпретирован по-разному.
Если класс обладает арифметическим (см. раздел 4.2) или побитовым (см. раздел 4.8) оператором, то его, как правило, имеет смысл снабдить соответствующими составными операторами. Вполне логично было бы также определить и оператор +=. Само собой разумеется, оператор += должен быть определен так, чтобы он вел себя аналогично встроенным операторам, т.е. осуществлял составное присвоение: сначала сумма (+), а затем присвоение (=).
Выбор обычной функции или члена классаПри проектировании перегруженных операторов необходимо принять решение, должен ли каждый из них быть членом класса или обычной функцией (не членом класса). В некоторых случаях выбора нет; оператор должен быть членом класса. В других случаях можно принять во внимание несколько эмпирических правил, которые помогут принять решение.
Приведенный ниже список критериев может оказаться полезен в ходе принятия решения о том, следует ли сделать оператор функцией-членом класса или обычной функцией.
• Операторы присвоения (=), индексирования ([]), вызова (()) и доступа к члену класса (->) следует определять как функции-члены класса.
• Подобно оператору присвоения, составные операторы присвоения обычно должны быть членами класса. Но в отличие от оператора присвоения, это не обязательно.
• Другие операторы, которые изменяют состояние своего объекта или жестко связаны с данным классом (например, инкремент, декремент и обращение к значению), обычно должны быть членами класса.
• Симметричные операторы, такие как арифметические, операторы равенства, операторы сравнения и побитовые операторы, лучше определять как обычные функции, а не члены класса.
Разработчики ожидают возможности использовать симметричные операторы в выражениях со смешанными типами. Например, возможности сложить переменные типа int и double. Сложение симметрично, а потому можно использовать тип как левого, так и правого операнда.
Если необходимо обеспечить подобные выражения смешанного типа, задействующие объекты класса, то оператор должен быть определен как функция, не являющаяся членом класса.
При определении оператора как функции-члена левый операнд должен быть объектом того класса, членом которого является этот оператор. Например:
string s = "world";
string t = s + "!"; // ok: const char* можно добавить к строке
string u = "hi" + s; // возможна ошибка, если + будет членом
// класса string
Если бы оператор operator+ был членом класса string, то первый случай сложения был бы эквивалентен s.operator+("!"). Аналогично сложение "hi" + s было бы эквивалентно "hi".operator+(s). Однако литерал "hi" имеет тип const char*, т.е. встроенный тип; у него нет функций-членов.
Поскольку класс string определяет оператор + как обычную функцию, не являющуюся членом класса, сложение "hi" + s эквивалентно вызову operator+("hi", s). Подобно любому вызову функции, каждый из аргументов должен быть преобразуем в тип параметра. Единственное требование — по крайней мере один из операндов должен иметь тип класса, а оба операнда могут быть преобразованы в строку.
Упражнения раздела 14.1Упражнение 14.1. Чем перегруженный оператор отличается от встроенного? В чем перегруженные операторы совпадают со встроенными?
Упражнение 14.2. Напишите объявления для перегруженных операторов ввода, вывода, сложения и составного присвоения для класса Sales_data.
Упражнение 14.3. Классы string и vector определяют перегруженный оператор ==, применимый для сравнения объектов этих типов. Если векторы svec1 и svec2 содержат строки, объясните, какая из версий оператора == применяется в каждом из следующих выражений:
(a) "cobble" == "stone" (b) svec1[0] == svec2[0]
(c) svec1 == svec2 (d) "svec1[0] == "stone"
Упражнение 14.4. Объясните, должен ли каждый из следующих операторов быть членом класса и почему?
(а) % (b) %= (с) ++ (d) -> (е) << (f) && (g) == (h) ()
Упражнение 14.5. В упражнении 7.40 из раздела 7.5.1 был приведен набросок одного из следующих классов. Какой из перегруженных операторов должен (если должен) предоставить класс.
(a) Book (b) Date (с) Employee
(d) Vehicle (e) Object (f) Tree
14.2. Операторы ввода и вывода
Как уже упоминалось, библиотека IO использует операторы >> и << для ввода и вывода соответственно. Сама библиотека IO определяет версии этих операторов для ввода и вывода данных встроенных типов. Классы, нуждающиеся во вводе и выводе, обычно определяют версии этих операторов для объектов данного класса.

