Б. Страуструп - Язык программирования С++. Специальное издание, 3-изд. Бином. 2004 (1160791), страница 67
Текст из файла (страница 67)
(*2) Определите класс Нв(оцгат, который хранит значения для некоторых интервалов, указанных в качестве аргументов конструктора. Напишите функции вывода гистограммы. Учтите случаи выхода значений за допустимый диапазон. 6. (*2) Определите несколько классов, генерирующих случайные числа, имеющие определенные распределения (напрнмер, равномерное и экспоненциальное). Пусть у каждого класса имеешься конструктор, задающий тип распределения, и функция с(гав, возврашающая случайное число.
7. (*2.5) Дополните класс ТаЫе для хранения пар (имя, значение). Затем модифицируйте программу качькулятора пз 9 6.1 таким образом, чтобы в ней использовался ТаЫе вместо тар. Сравните две версии. 8. (*2) Перепиши~с Тпос(е из 9 7.10[7] в виде класса с конструкторами, деструкторами и т. д. Определите дерево с узлами Топая в виде класса с конструкторами, деструкторами и т, д. 9. (*3) Определите, реализуйте и отгестпруйте класс!пгвег д |я множества целых чисел. Реализуйте операции объединения, пересечения и симметричной разности. 10. (*1.5) Сделайте из класса!пгзег множество узлов Мос(е, где л1ос(е является определенной вами структурой. 11. ('3) Определите класс для анализа, хранения, вычисления и печати простых арифметических выражений, состоящих из целых констант и операторов +, —, * и /. Открытый интерфейс должен выглядеть следуюшим образом: сЕисв Ехрг ( 0- риЫ1с.
Екрг )сйаг'), 1пс ева1 )), во! с( р Нас )), 10.б.упражнения 307 Строковый аргумент конструктора ЕхргсЕхрг )) является выражением. с)зункция Ехргсева1 )) возвращает значение выражения, и Ехргсрг!и1)) выводит представле- ние выражения в сои!, Программа может выглядеть следующим образом: Екргх ) 123?4+123'4-3') сои! « "х = " «х.еоа1 )) « "1п', к,рплг )); Определите класс Ехрг дважды: один раз с использованием в качестве представ- ления связного списка узлов, и другой — с использованием строк.
Поэкспери- ментируйте с различными способами печати выражения: с расставленными скоб- ками, в пастфиксной нотации и т. д. крытый интерфейс не зависел от представления. Реализуйте Сйиг лиепе: а) в виде связнога списка; б) в виде вектора. Не думайте о мнагозада ~ности. 13. ('3) Разработайте класс таблицы символов п класс элементов таблицы символов для какого-нибудь языка. Посмотрите компилятор для этого языка. Как выгля- дит в действительности табзлгща символов? РС (*2) Измените класс выражений из 9 10.6(11) такигн образом, чтобы ан мог абра батывать переменные н оператор присваивания =.
Воспользуйтесь классом таб- лицы символов из з 10.6[13]. 15. ('1) Имеется программа; и!ос!аде с!ов1геат> )л1та!п )) вЫ сои! « "Здравствуй, мире,л'; ) !ч(одпфпцпруйте ее таким образом, чтобы она выводила: Инициализация Здравствуй, мир! Очистка Не делайте при этом никаких изменений в таси )), 16. (*2) Определите класс Са1си!а(ог, большая часть которого реализуется при по- мощи функций из 9 6,1. Создайте калькуляторы п вызовите их с аргументом пз с!л, из командной строки и строки в про~рамме. Реализуйте возможность вывода в различные места назначения, аналогично вводу. ("2) Определите два класса, каждый из которых имеет статический член, таким образом, чтобы конструктор каждого статического члена содержал в себе ссылку на другой.
Где в реальном коде можно встретить такие конструкции? Как можно исключить зависимость от порядка в таких конструкторах? 17 18. (*2.5) Сравните класс Ра(е (ч 103) с вашим решением упражнений б 5.9(13) и 9 7.10(19). Обсудите найденные ошибки и возможные различия при сопровождении каждого пз решений, 12. (*2) Определнте класс Сйаг диеие (очередь символов) таким образом, чтобы от- 308 Глава 10.
Классы 19. ('3) Напишите функцию, получающую в качестве аргументов ькйеат и пестог<з1гтд> и возвращающую тар<з1ппн, оесМог~т1». Последний ассоциативный массив должен содержать каждую строку и количество раз, которое она встречалась. Запустите программу с тскстовым файлом разгиером не менее 1000 строк, пща при этом не менее 10 слов, 20. ('2) Возьмите класс Еп1гу пз 8 В.8.2 и модифицируйте его таким образом, чтобы каждый член объединения всегда использовался в соответствии с его типом. Перегрузка операторов Когда я иогользгую слово, оно отгичает то, что я хочу, не больше и не меньше.
— Шазгтай-Болтай Обозначения — операторные функции — бинарные и унарные операторы— предопределенный смысл операторов — смысл операторов, определяемый пользователем -- операторы и пространства имен комплексный пш— операторы-члены и не-члены — смешанная арифмегика — инициазгизация— копирование — преобразования — литералы — функции-помошники — операторы преобразования — разрешение неоднозначности —. друзья — члены и друзья— большие объекты — присваивание и инициализация — индексация — вызов функции — разыменование — инкремент и декремент — класс строк — советы— упражнения.
11.1. Введение В каждой технической области — и в большинстве не технических — имеются свои стандартные обозначения, облетгаклцгие представление н обсуждение часто встречающихся концепции. Например, благодаря постоянному использованию, вырал.ение Х'у'2 яснее для нас, чеы фраза умножить у на в и прибавить результат и к Трудно переоценить значение краткой п выразительной формы записи типичных операций.
Как и бо льш инство друпгх языков С+в поддерживает набор операторов для встроенных типов. Однако большинство концепций, для которых обычно используются операторы, не являются встроенными типами С+-~, поэтому они долзкны быть представлены в виде типов, определяемых пользователем. Например, если вам требуется комплексная арифметика, матричная алгебра, сигнальная логика нли символьные строки в С~-~, вы пользуетесь механизмом классов для представления этих понятий. Определение операторов для таких классон иногда позволяет программисту реализовать более привычнуго и удобную форму записи для манипулирования объектами, чем та, которая доступна с использованием только базовой функциональной формы записи, Например, Глава 11.
Перегрузка операторов 310 с!аее са>пр1ех ( >»> о >ень упрои(епньщ класс сотр!ех с(оиЫе ге, !т; рибйс со>пр!ех (с!оиЫе г, с)оиЫе!) ге (>'), т (1) (] сот р!ех орега1пг+ (сотр!ех), сотр!ех ореги1аг' (сотр!ех), определяет простую реализацию концепции ком гщексного числа. Класс сотр1ех представ лен парой щсел с плаваю>цей точкой двойной точности и двумя операторами + и '. Программист вводит операторы со>пр1ехзореги1ог+ () и сотр!ехзорега1ог* (), которые определяют смысл операций сложения и умножения. Например, если и Ь и с имеют тип со>пр1ех, Ь+с означает Ь.орегагог+(с).
Теперь мы можем записать комплексные выражения в форме, близкой к общепринятои: оо1>(У() ( сотр1ех а = сотр1ех (1, а 1), сотргех Ь =- сотр!ех (1.2, 2), сотр1ех с = Ь, а =Ь+с, Ь = Ь+с" а, с = а*Ь+сотр(ех (1, 2); Выполняются обычные правила приоритета операций, поэтому вторая инструкция означает Ь=Ье(с*а), а не Ь=(Ь+с)*а.
Наиболее очевидное использование пере>руженных операторов — применение их к конкретным типам (9 10.3). Однако польза от операторов, определяемых пользователем, нс ограничивается только конкретными тит>ами. Например, проектирование обобщенных и абстрактных интерфейсов часто приводит к использованию операторов, таких как ->, [] и (). 11.2. Операторные функции Можно объявить функции, определяющие смысл следующих операторов Я 6.2): ь> ь « » зъ «= >< с!е1е1е >(е)еге(] лет[] пее> Следующие операторы не могут быть определены пользователем: ;: (разрешение области видимости; 9 4.9.4, 9 10.2.4); (выбор члена; ч 5.2>); .' (выбор члена через указатель на член; 9 15.5). Правым операндом у них является не значение, а имя, и опи предоставляют основные средства доступа к ч.лснам.
Разрешение их перегрузки привело бы к очень тонким о>пибкам [Вггоиесгпр, 1994]. Тернарный условный оператор з: также не может быть перегружен. Аналогично не могут быть прегружецы операторы е!хео~Я 14 6) и гуре!с((6 15 А 4). 11.2. Операторные функции оо(с(г (сотр1ек а, сотр1ек Ь) соьпр1ек с = и -г Ь, согвр1ек с( = а орега1ог+ (Ь); ) 1( сокращенная грорла О явный вызов При вали шп предыдущего определения сотр1ех обе инструкции являются синонимами. 11.2.1.
Бинарные и унарные операторы Бинарный оператор можно определить либо в виде нестатичсской функции-члена с одниги аргументов, либо в виде функции-не-члена с двумя аргументами. Для любого бинарного оператора Р выражение аа(: ЬЬ интерпретируется либо как аа.прага(огФ(ЬЬ) либо орега(огй(аа, ЬЬ).
Если определены обе функции, для выяснения того, какую (возможно никакую) из них использовать, применяется механизм разрешения перегрузки (Ь ?з(). Например: с(аьвХ( риИс ооЫорега1ог+ (тф Х(т1), ооЫ орегагог-г ,'Х, Х), ооЫ орега(огь (Х, йоиЫе); ооЫ)'(Ха) ( аь1, 1еа, а-г1 0; ,17 а.орега1огг(1) )ь::прего(огь(Х(1), а) 11 лорега1огь(а, 1.0) Унарный оператор, префиксный илп постфиксный, можно определить либо в виде нсстатической функции-члена без аргументов, либо в виде функции-не-члена, с одним аргуьье«тоьь Для любого унарного оператора Р выражение Раа интерпретируется либо как аа.орега(огй (), либо как орегатогФ (аа).
Если определены обе функции, для определения гого, какую (возможно, никакук~) из нпх использовать, Невозможно определить новую лексему оператора, но вы можете воспользоваться функцией, если вас не устраивает существующий набор операторов. Например, вы можете написать рот () вместо **. Это ограничение может показаться очень строгим, но более гибкие правила легко могут привести к неоднозначности. Например, определение оператора ** для обозначения степени может на первый взгляд показаться очевидной и легкой задачей, но подумайте еще раз.
Должен ли '* быть левоассоцнативным (как в Еогггап) или правоассоциативным (как в А)йо()? Выражение а**р должно интерпретироваться как а* ('р) или как (а)** (р)? Имя операторной функции начинается с ключевого слова орега1ог, за которым следует сам оператор; например орега(ог«, Операторная функция объявляется и может быть вызвана, как любая другая функция. Использование операторной функции как оператора является просто сокращенной формой ее явного вызова.