Б. Страуструп - Язык программирования С++. Специальное издание, 3-изд. Бином. 2004 (1160791), страница 89
Текст из файла (страница 89)
[12] Отлаживайте конкретные примеры до нх обобщения в шаблоны; 6 13.2.1. [13] Не забывайте экспортировать (ехрог1) определения шаблонов, доступ к которым необходим из других единиц трансляции; 9 13.7. [14] Компилируйте раздельно большие шаблоны и шаблоны с нетривиальными зависимостями от контекста; 9 13.7. [15] Используйте шаблоны для определения преобразований, но определяйте эти преобразования очень внимательно; 9 13.6.3.1.
[16) При необходимости ограничивайте аргументы шаблона при помощи функциичлепа солз1гат1(); 6 13.9[16]. [17] Используйте явную форму инстанцирования для минимизации времени компиляции и компоновки; 9 В.13.10. [18] Отдавайте предпочтение шаблонам по отношению к производным классам, когда эффективность времени выполнения имеет исключительное значение; 9 13.6.1. [19] Отдавайте предпочтение производным классам по отношению к шаблонам, если большое значение имеет добавление нового варианта без перекомпиляции; 9 13.6.1. [20] Отдавайте предпочтение шаблонам по отношению к производным классам, когда нельзя определить общий базовый класс; й 13.6.1. [21] Отдавапте предпочтение шаблонам по отношению к производным классам, если вы должны использовать встроенные типы и структуры из-за соображений совместимости; 9 13.6.1, 13.9. Упражнения 1.
(*2) Устраните ошибки в определении Пз1 в 9 13.25 и напишите на С+а код, эквивалентный тому, что должен сгенерировать компилятор для определения Аз( и функции 1 [). Выполните небольшой тест с вашим кодом, чсгенернрованнымь вручную и с кодом, сгенерированным компилятором из версии с шаблоном.
Если вы знаете, как это сделать в вашей системе, сравните сгенерированные машинные коды. 2. (*3) Напишите шаблон класса односвязного списка, который принимает элементы любого типа, производного от класса Етя, имеющего всю информацию, необходимую для связывания элементов. Такой список называется интрузивным. При помощи этого списка напишите односвязный список, который принимает элементы любого типа (неинтрузивпый список). Сравните производительность обоих классов списков н обсудите разницу. 13.9. Упражнения 405 3.
(*2,5) Напишите интрузивные и неинтрузнвные двусвязныс списки. Какие до- полнительные операции нужно реализовать по сравнению с теми, которые вы сочли нужным ввести для односвязных сцисков? 4. ('2) Завершите шаблон 81г1пдиз 9 13,2, основанный на классе 81г(приз 9 11.12 5. («2) Определите шаблон функции зог1(), который получает критерий сравне ния в виде аргумента шаблона. Определите класс Яесогс(с двумя членами соип1 и рг1се. Отсортируйте эес1ог пегого> по каждому члену. 6.
(*2) Реализуйте шаблон дзогт []. 7. (*2) Напишите программу, которая читает пары (яеу, эа1ие) (ключ, значение) и выводит сумму всех оа1ие, соответствующих каждому йеу. Укажите, какие требования должны предъявляться к типам яеу и еа1ие. 8. (*2.5) Реализуйте простой класс Ма]э (ассоциативный массив), основанный на классе Аззос из 9 11.8. Убедитесь, что Мар правильно работает и с С-строками, и со строками з1г1пдв качестве ключей. Убедитесь, что Мар правильно работает с типами, как имеющими, так и не имеющими конструкторы цо умолчанию. Реализуйте механизм итерации по элементам Мар.
9. (*3) Сравните производительность программы подсчета слов из 9 11.8 с про граммой, не использующей ассоциативного массива. В обоих случаях, используйте одни и тот же стн.ль ввода/вывода. 10. (*3) Реализуйте заново Мар из 9 13.9[8] с использованием более подходящих структур (например, «красно-черное дерево» или Яр!ау-дерево). 11. ('2.5) Воспользуйтесь Мар для реализации функции топологической сортиров ки. Топологическая сортировка описана в [Кпцс]к 1968], том 1 (второе издание), стр, 262. 12. (*1.5) Перепишите программу суммирования из 9 13.9[7] так, чтобы она правильно работала с именами, содержащими пробелы, например «член данных». 13, (*2) Напишите шаблоны геа811пе [] для различных форматов строк (][вез).
На пример (ианменованне, количество, цена). 14. (*2) Используйте технику, кратко описанную для И1ега1е в 9 13.4, для сорти ровки строк в обратном лексикографическом порядке. Убедитесь, что этот метод работает как для реализаций С++, где сйаг является з1даеЫ, так и для тех, где сйаг — ипз1йпей. Воспользуйтесь вариацией этой техники для реализации сортировки независимо от регистра. 15. ("1.5) Напишите пример, который демонстрирует по крайней мере три различия между шаблоном функции и макросом (не считая разницы в синтаксисе определения). 16. (*2) Разработайте схему, которая гарантирует, что компилятор проверяет общие ограничения на аргументы шаблона для каждого шаблона, для которого создается объект.
Недостаточно просто проверить ограничения типа «аргумент Т должен быть класса, производного от Му базе». Обработка исключений Не перебивайте женя, когда я вас перебиваю, — Уинстон В. Черчилль Обработка ошибок — группировка исключений — перехват исключений— перехват всех исключении — повторная генерация — управление ресурсами — аи(о р(г — исключения и пеш — исчерпание ресурсов— исключения в конструкторах — исключения в деструкторах — исключения, не являющиеся ошибками — спецификации исключений — неожидаемые исключения — неперехвачеиные исключения — исключения и эффективность — альтернативные методы обработки ошибок стандартные исключения — советы — упражнения. 14.1.
Обработка ошибок Как отмечалось в з 8.3, автор библиотеки может обнаружить ошибки времени выполнения, но, в общем случае, не имеет ни малейшего представления, что с ними делать. Пользователь библиотеки может знать, как бороться с такими ошибками, но нс может нх обнаружить — в противном случае, они бы обрабатывались в коде пользователя, н их обнаружение не было бы возложено на библиотеку. Для помощи в решении подобных проблем введено понятие ис лючения. Фундаментальная идея состоит в том, что функция, обнаружившая проблему, но не знающая как ес решить, генерирует (Спгот) исключение в надежде, что вызвавшая ее (непосредственно илп косвенно) функция сможет решить возникшую проблему.
Функция, которая хочет решать проблемы данного типа, может указать, что она перехватывает (сассЬ) такие исключения (з 2А.2, з 8.3). Такой стиль обработки ошибок предпочтительней многих традиционных техник, Рассмотрим альтернативы. При обнаружении проблемы, которая не может быть решена локально, функция может: прекратить выполнение, [2] возвратить значение, означающее «ошибка», [3] возвратить допустимое значение и оставить программу в ненормальном состоянии: [й] вызвать функцию, предназначенную для обработки «ошибочных» ситуаций. Вариант []] — «прекратить выполнение» вЂ” это то, что происходит по умолчанию, когда не перехватывается исключенце.
Для большинства ошибок мы можем н долж- 408 Глава 14. Обработка исключений ны придумать кое-что получше. В частности, библиотека, которая не знает о цели н общей стратегии программы, ее использующей, не может просто выйти (функцией ех11 [)) нз программы или прервать ее выполнение (функцией абог1 ([). Библиотека, безусловно завершающая выполнение, не может использоваться в программе, первое требование к которой — яадежность. Одним из способов представления исключений является их рассмотрение в качестве средства передачи управления вызывающей функции, когда локально невозможно вьптолнить никаких разумных действий.
Вариант [21 — «возвратить значение, сигнализирующес об ошибке» вЂ” не всегда выполним, потому что часто нет приемлемого соответствующего значения. Например, если функция возвращает ~1елое, любое целое может быть приемлемым результатом. Дажс в тех случаях, когда такой подход применим, он часто неудобен, потому что результат каждого вызова должен проверяться на ошибочное значение.
Это легко может удвоить размер программы Я 14.8), Поэтому такой подход редко используется систематически для обнаружения всех ошибок. Вариант [3] — «возвратить допустимое значение и оставить программу в ненормальном состоянии» вЂ” имеет тот недостаток, что вызывающая функция может пе заметить, что программа находится в ненормальном состоянии. Например, многие стандартные функции библиотеки С устанавливают значение глобальной переменной еггао для индикации ошибки (з 2ОА.1, з 22.3). Однако программы в большинстве случаев не проверяют еггло достаточно систематически, чтобы избежать последующих ошибок, вызванных значениями, возвраа1енными некорректно завершившимися функциями. Более того, использование глобальных переменных для записи информации об ошибках работает неудовлетворительно при наличии параллельных процессов.
Обработка исключений не предназначена для решения проблем, для которых подходит вариант [41 «вызвать функцию обработки ошибок». Однако в отсутствие исключений у функции обработки ошибок имеется в точности те же самые три указанные альтернативы, как обрабатывать ошибку. Дальнейшее обсуждение функций обработки ошибок см. в ~ 14.4.5. Механизм обработки исключений предоставляет альтернативу традиционным методам в тех случаях, когда они не достаточны, нс элегантны и подвержены ошнокам.
Он предоставляет способ явного отделения кода обработки ошибок от «обычного» кода, делая таким образом программу более читабельной и лучше подходящей для различных инструментальных средств. Механизм обработки исключений предоставляет более регулярный способ обработки ошибок, упрощая в результате взаимодействие между отдельно написанными фрагментами кода. Одним нз аспектов обработки исключений, который будет новым для программистов на С и Рааса!, является то, что по умолчанию реакцией на ошибку (особенно на ошибку в библиотеке) будет завершение выполнения программы.