Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
КРАТКИЙ ОБЗОР С.doc
Скачиваний:
1
Добавлен:
26.10.2018
Размер:
2.11 Mб
Скачать

* Глава 7

      Если я выбираю слово, оно значит только то,       что я решу, ни больше и ни меньше.       - Шалтай Болтай       Глава содержит описание механизма перегрузки операций в С++.       Программист может задать интерпретацию операций, когда они       применяются к объектам определенного класса. Помимо арифметических,       логических и операций отношения можно переопределить вызов       функций (), индексацию [], косвенное обращение ->, а также       присваивание и инициализацию. Можно определить явные и скрытые       преобразования между пользовательскими и основными типами. Показано,       как определить класс, объект которого можно копировать и       уничтожать только с помощью специальных, определенных пользователем       функций.

7.1 Введение

      Обычно в программах используются объекты, являющиеся конкретным       представлением абстрактных понятий. Например, в С++ тип данных int       вместе с операциями +, -, *, / и т.д. реализует (хотя и ограниченно)       математическое понятие целого. Обычно с понятием связывается набор       действий, которые реализуются в языке в виде основных операций над       объектами, задаваемых в сжатом, удобном и привычном виде.       К сожалению, в языках программирования непосредственно представляется       только малое число понятий. Так, понятия комплексных чисел, алгебры       матриц, логических сигналов и строк в С++ не имеют непосредственного       выражения. Возможность задать представление сложных объектов вместе       с набором операций, выполняемых над такими объектами,       реализуют в С++ классы. Позволяя программисту определять операции       над объектами классов, мы получаем более удобную и традиционную       систему обозначений для работы с этими объектами по сравнению с той,       в которой все операции задаются как обычные функции. Приведем пример:       class complex {       double re, im;       public:       complex(double r, double i) { re=r; im=i; }       friend complex operator+(complex, complex);       friend complex operator*(complex, complex);       };       Здесь приведена простая реализация понятия комплексного числа, когда       оно представлено парой чисел с плавающей точкой двойной точности,       с которыми можно оперировать только с помощью операций + и *.       Интерпретацию этих операций задает программист в определениях функций       с именами operator+ и operator*. Так, если b и c имеют тип complex,       то b+c означает (по определению) operator+(b,c). Теперь можно       приблизиться к привычной записи комплексных выражений:       void f()       {       complex a = complex(1,3.1);       complex b = complex(1.2,2);       complex c = b;       a = b+c;       b = b+c*a;       c = a*b+complex(1,2);       }       Сохраняются обычные приоритеты операций, поэтому второе выражение       выполняется как b=b+(c*a), а не как b=(b+c)*a.

7.2 Операторные функции

Можно описать функции, определяющие интерпретацию следующих операций:       + - * / % ^ & | ~ !       = < > += -= *= /= %= ^= &=       |= << >> >>= <<= == != <= >= &&       || ++ -- ->* , -> [] () new delete       Последние пять операций означают: косвенное обращение ($$7.9),       индексацию ($$7.7), вызов функции ($$7.8), размещение в свободной       памяти и освобождение ($$3.2.6). Нельзя изменить приоритеты этих       операций, равно как и синтаксические правила для выражений. Так,       нельзя определить унарную операцию % , также как и бинарную операцию       !. Нельзя ввести новые лексемы для обозначения операций, но если       набор операций вас не устраивает, можно воспользоваться привычным       обозначением вызова функции. Поэтому используйте pow(), а не ** .       Эти ограничения можно счесть драконовскими, но более свободные       правила легко приводят к неоднозначности. Допустим, мы определим       операцию ** как возведение в степень, что на первый взгляд кажется       очевидной и простой задачей. Но если как следует подумать, то       возникают вопросы: должны ли операции ** выполняться слева направо       (как в Фортране) или справа налево (как в Алголе)? Как       интерпретировать выражение a**p как a*(*p) или как (a)**(p)?       Именем операторной функции является служебное слово operator, за       которым идет сама операция, например, operator<<. Операторная       функция описывается и вызывается как обычная функция. Использование       символа операции является просто краткой формой записи вызова       операторной функции:       void f(complex a, complex b)       {       complex c = a + b; // краткая форма       complex d = operator+(a,b); // явный вызов       }       С учетом приведенного описания типа complex инициализаторы в этом       примере являются эквивалентными.