Программирование >>  Структурное программирование 

1 ... 179 180 181 [ 182 ] 183 184 185 ... 342


гому объекту того же самого класса, но с помощью конструкторов преобразования она может также использоваться для присваиваний объектов различных классов.

Если перегруженная операция присваивания не определена, присваивание все-таки возможно, но по умолчанию при этом проводится побитовое копирование каждого элемента данных. Для объектов, которые содержат указатели на динамически выделенные области памяти, подобное копирование приводит к тому, что два разных объекта указывают на одну и ту же динамически выделенную область памяти. Выполнение деструктора любого из этих объектов освобождает эту динамически выделенную область памяти. Если теперь обратиться к другому объекту, указывающему на эту освобожденную область памяти, то результат будет непредсказуемым.

Чтобы перегрузить операцию инкремента для получения возможности использования и префиксной, и постфиксной форм, каждая из этих двух перегруженных функций-операций должна иметь разную сигнатуру, чтобы компилятор имел возможность определить, какая версия ++ имеется в виду в каждом конкретном случае. Префиксный вариант перегружается точно так же, как любая другая префиксная унарная операция. Обеспечение уникальной сигнатуры функции операции постфиксной формы инкремента достигается с помощью фиктивного аргумента типа int. Пользователь может не задавать никакого значения этому аргументу. Он вводится просто для того, чтобы помочь компилятору различать префиксные и постфиксные формы операций инкремента и декремента.

Терминология

встроенный тип класс Array класс Date класс String ключевое слово operator конструктор копии конструктор преобразования неперегружаемые операции неявные преобразования типов операции, допускающие перегрузку операция преобразования перегруженная дружественная

функция-операция перегруженная операция != перегруженная операция перегруженная операция перегруженная операция перегруженная операция перегруженная операция перегруженная операция [] перегруженная операция

присваивания (=)

<

<=

> >=

перегруженная функция-операция элемент перегрузка

перегрузка бинарной операции перегрузка операций перегрузка постфиксной операции перегрузка префиксной операции перегрузка унарной операции преобразование, определенное

пользователем преобразования между

встроенными типами и классами преобразования между типами

классов сцепленные вызовы функций тип, определенный пользователем функции-операции функция преобразования явные преобразования типа

(с помощью приведений типов)



Хороший стиль программирования

8.1 Используйте перегрузку операций, если она делает программу более ясной по сравнению с применением явных вызовов функций для выполнения тех же операций.

8.2 Избегайте чрезмерного или непоследовательного использования перегрузки операций, так как это может сделать программу непонятной и затруднит ее чтение.

8.3 Перегружайте операции, чтобы они выполняли над объектами класса ту же функцию или близкие к ней функции, что и операции, выполняемые над объектами встроенных типов.

8.4 Перед написанием программы на С++ с перегруженными операциями обратитесь к руководству по вашему компилятору С++, чтобы осознать разнообразные специфические ограничения и требования отдельных операций.

8.5 Чтобы обеспечить согласованность связанных операций используйте одни из них для реализации других (т.е. используйте перегруженную операцию + для реализации перегруженной операции +=).

8.6 При перегрузке унарных операций предпочтительнее создавать фук-ции-операции, являющиеся элементами класса, вместо дружественных функций, не являющихся элементами. Дружественных функций и дружественных классов лучше избегать до тех пор, пока они не станут абсолютно необходимыми. Использование друзей нарушает инкапсуляцию класса.

8.7 Конструктор, деструктор, перегруженную операцию присваивания и конструктор копии обычно применяют совместно для класса, который использует динамически распределенную память.

Типичные ошибки программирования

8.1 Попытка перегрузить операцию, запрещенную для перегрузки.

8.2 Попытка создавать новые операции.

8.3 Попытка изменить работу операции с объектами встроенного типа.

8.4 Предположение, что перегрузка операции (такой как +) автоматически перегружает связанные с ней операции (такие как +=). Операции можно перегружать только явно; неявной перегрузки не существует.

8.5 Отсутствие проверки самоприсваивания при перегрузке оператора присваивания для класса, имеющего указатель на динамическую область памяти.

8.6 Не предусматривают перегруженную операцию присваивания и конструктр копии для класса, когда объекты этого класса содержат указатели на динамически распределенную память.



Замечания по технике программирования

8.1 Перегрузка операций способствует расширяемости С-Ы-, являясь, несомненно, одним из наиболее привлекательных свойств этого языка.

8.2 По меньшей мере один аргумент функции-операции должен быть объектом класса или ссылкой на объект класса. Это предохраняет программиста от изменения работы операции с объектом встроенного типа.

8.3 Новые возможности ввода-вывода для типов, определенных пользователем, могут быть добавлены в С++ без изменения объявлений или закрытых данных-элементов для классов ostream и istream. Это еще один пример расширяемости языка программирования С++.

8.4 Можно запретить присваивание одного объекта класса другому. Это делается путем определения операции присваивания как закрытого элемента класса.

8.5 Можно предохранить объекты класса от копирования; для этого просто делают закрытыми и перегруженную операцию присваивания, и конструктор копии.

8.6 При применении конструктора преобразования для выполнения неявного преобразования типов С-Ы- может использовать неявный вызов только одного конструктора, чтобы попытаться удовлетворить требование другой перегруженной операции. Невозможно удовлетворять требования перегруженных операций путем выполнения последовательности неявных определенных пользователем преобразований.

Упражнения для самопроверки

8.1 Заполнить пробелы в следующих утверждениях:

а) Предположим, что а и b - целые переменные и мы формируем сумму а -I- Ь. Теперь предположим, что end - переменные с плавающей запятой и мы формируем сумму с + d. Очевидно, что две

Советы по повышению эффективности

8.1 Можно было бы перегружать операцию не как элемент и не как дружественную функцию, но такая функция, нуждающаяся в доступе к закрытым или защищенным данным класса, потребовала бы использования функций set или get, предусмотренных открытым интерфейсом этого класса. Накладные расходы на вызовы этих функций могли бы вызвать ухудшение производительности.

8.2 Наличие перегруженной операции сцепления +=, которая получала бы один аргумент типа const char*, более эффективно, чем выполнение сначала неявного преобразования, а затем сцепления. С другой стороны, неявные преобразования требуют меньшего объема кодирования и вызывают меньше ошибок.



1 ... 179 180 181 [ 182 ] 183 184 185 ... 342

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика