Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
пиппец 2.doc
Скачиваний:
107
Добавлен:
07.06.2015
Размер:
3.16 Mб
Скачать

60. Выражения и операции. Перегрузка операций.

Выражения – это простейший способ организации действий в алгоритмах; это грамматическая конструкция, включающая операнды, операции, символы разделители. Выражение задают порядок вычисления единственного значения некоторого типа.

Операнды – то над чем выполняется операция: 1)константы (литерал) – это лексема, представляющая изображение фиксированного числового, строкового или символьного (литерного) значения; 2)идентификаторы (переменные) – последовательность из букв латинского алфавита, десятичных цифр и символов подчеркивания, начинающаяся не с цифры; 3)другие выражения.

Символы-разделители - знаки пунктуации: [] () {} , ; : … * = # &, каждый из которых выполняет свою функцию.

Операции - определяются знаком операции и задают правила преобразования информации.

Приоритет операций или ранги операций: операции первого ранга имеют наивысший приоритет; операции одного ранга имеют одинаковый приоритет, и если их в выражениях несколько, то они выполняются в соответствии с правилом ассоциативности.1р()[]->; 2р!~+-++--&*(тип)sizeof; 3р*/%; 4р+; 5р<<>>; 6ротношения(< <= >= >) 7ротношения==!= 8p& 9p^ 10p| 11p&& 12p || 13p ?: 14p = 15,

Операции по количеству операндов делятся на следующие группы:

1)Унарные операции (&операция получения адреса операнда, *операция обращения по адресу, -унарный минус изменяет знак арифметического операнда, +унарный плюс введен для симметрии с унарным минусом, ~поразрядное инвертирование внутреннего двоичного кода целочисленного аргумента, !не – логическое отрицание, ++увеличение на единицу(инкремент)(префиксная – увеличение операнда на 1 до использования , постфиксная – увеличение значения операнда на 1 после его использования), --уменьшение(декремент) на 1, sizeof – операция вычисления размера для объекта).

2) Бинарные операции. Эти операции делятся на

аддитивные(+бинарный плюс-сложение, -бинарный минус -вычитание),

мультипликативные(*умножение, /деление, %получение остатка от деления),

сдвигов(<<сдвиг влево битового представления значения левого целочисленного операнда на количество разрядов, >>сдвиг вправо битового образа ),

поразрядные(&поразрядная конъюнкция, |поразрядная дизъюнкция, ^поразрядное исключающее или),

операции отношений(< > <= >= == !=),

логические(&&конъюнкция арифм.операндов, ||дизъюнкция арифметических операндов),

присваивания(=, *=, /=, %=, +=, -= и др.)

3)Тернарные операции. Напр., операции условия (знаки ? и :)

По типу операции бывают: арифметические(+,-,*,/, %-остаток от деления, инкремент++, декремент--), отношения(>=,<=,==,!=), логические(И&&, или ||, лог.не ! принимают значение 1 истина, 0ложь), поразрядные логические, др (операция присваивания =, операция последовательного вычисления(запятая), пр. for(i=1,j=2;i=j<20;i++,j++), операция приведения типа ((<имя типа>)<выражение>), sizeof р-том опер-и является размер в байтах типа или объявленной переменной. Применение операций к массивам возвращает число байтов, необходимое для размещения в памяти всех элементов массива, пр. int i,r;char c; long double f; r=sizeof char;(r=1), r=sizeof i;(r=2)).

Перегрузка операций – возможность различной интерпретации одного и того же символа операции различным образом в зависимости от числа или типа ее операндов. Для реализации перегрузки операций над объектами класса используют специальные функции – функции-операции. Синтаксис функции-операции: <тип возвращаемого значения > operator @ (<список аргументов>) {<тело функции>}, где @ - символ перегружаемой операции, тело функции определяет те действия, которые нужно сделать для реализации операции, operator – ключевое слово. В теле функции задается смысл перегружаемой операции. При перегрузке совсем не требуется, чтобы операция выполняла те действия, которые заложены в ее смысл.

Пример, сравнение двух комплексных чисел.#include<iostream.h> class Complex{ double real; double image;public:Complex (double r, double i){real=r;image=i;} ~Complex(){}int operator == (Complex &);int operator > (Complex &);int operator < (Complex &);};int Complex :: operator == (Complex & c) {if ((sqrt(real*real=image*image) == sqrt(c.real*c.real+c.image*c.image))) return1; else return0;}int Complex :: operator > (Complex & c) {if((sqrt(real*real=image*image)>sqrt(c.real*c.real+c.image*c.image))) return1; else return0;}int Complex :: operator < (Complex & c) {if((sqrt(real*real=image*image) < sqrt(c.real*c.real+c.image*c.image))) return1; else return0;}void main(){Complex c1(10.34, 77.2), c2(20.45, 77.2); if (c1>c2) count << “c1>c2” << endl; else count << “c1<=c2”<<endl;}

a>b и a.operator>(b) эквивалентно.

Функция-операция может быть: либо член класса, либо внешняя функция, но привилегированная в этом классе, либо обычная внешняя функция.

Пр: функция перегрузки операции сложения двух комплексных чисел является членом класса Complex: class Complex { double real; double image; public: Complex (double r=0,double i=0){real=r; image=i;}Complex& operator+ (Complex&);}; Complex& Complex :: operator+(Complex& c){ Complex& tmp=*(new Complex); tmp.real = real + c.real; tmp.image = image = c.image; return tmp; }

Прр: функция перегрузки операции сложения двух комплексных чисел является привилегированная функция в классе Complex:class Complex

{ friend Complex& operator+ (Complex&, Complex&); double real; double image; public: Complex (double r=0,double i=0){real=r; image=i;} };Complex& operator+(Complex& c1, Complex& c2){ Complex& tmp=*(new Complex); tmp.real = c1.real + c2.real; tmp.image = c1.image = c2.image; return tmp; }

Пр: функция перегрузки операции сложения двух комплексных чисел является обычной внешней функцией:class Complex{ double real; double image; public: Complex (double r=0,double i=0){real=r; image=i;}double& get_real() return real;}double& get_image() {return image;}void set_real (double r) {real=r;}void set_image (double i) {image=i;}};Complex& operator+(Complex& c1, Complex& c2){ Complex& tmp=*(new Complex); tmp.set_real(c1.get_real()+c2.get_real()); tmp.set_image(c1.get_image()+c2.get_image()); return tmp; }

Правила перегрузки операций:

1)Операции, не допускающие перегрузки: . .* ?: :: sizeof

2)Язык не допускает возможности определить для операции новый лексический символ, кроме тех, что определены в языке. Т.к. компилятору неизвестен приоритет нового знака операции, а значит, и порядок вычисления сложного выражения.

3)Не допускается перегрузка операций для встроенных типов данных. Например, нельзя переопределить операцию сложения целых чисел.

4)Нельзя определить дополнительную операцию для встроенных типов.

5)Нельзя переопределить приоритет операции.

6)Нельзя изменить синтаксис операции в выражении. Если некоторая операция определена в языке как унарная, то ее нельзя переопределить как бинарную.

7)При перегрузке операций ++ и – не сохраняется различие между префиксной и постфиксной формами записи.

8)При перегрузке унарной операции: а) если функция-операция является членом класса, то она не должна иметь аргументов (фактически ей всегда передается неявный аргумент – указатель this на текущий объект), т.е. для любой унарной операции @ запись @obj интерпретируется как obj.operator@(); б) если ф-о явл. внешней функцией, то она имеет один аргумент (ссылку на объект), т.е. =//= как operator@(obj).

9)При перегрузке бинарной операции: а) если функция-операция является членом класса, то она должна иметь один явный аргумент (ссылку на объект), другой аргумент - указатель this на текущий объект (передается неявно), т.е. для любой бинарной операции @ запись obj1@obj2 интерпретируется как obj1.operator@(obj2); б) если ф-о явл. внешней функцией, то она имеет два аргумента (ссылки на объекты), т.е. =//= как operator@(obj1, obj2).

10)Если левый операнд перегружаемой бинарной операции представляет не пользовательский тип, а один из встроенных типов, то тогда такая операция не может быть перегружена как член класса. Тогда операция должна быть определена как внешняя функция, у которой первый аргумент – один из встроенных типов, а второй – пользовательский тип.

11)Операции = [] () -> должны перегружаться как члены класса.

12)Операции присваивания и взятие адреса предопределены языком для любого определенного пользователем типа, т.е. если пользователь не перегрузил эти операции, они все равно действительны. Предопределение присваивания – это просто поэлементное копирование.Количество аргументов функции-операции. Перегрузка операции присваивания.class Vector{..public: Vector& operator=(Vector&v);}; Vector& Vector::operator=(Vector& v){if (this==&v} return *this; if(a!=null) delete []1; if(v.a==null) a==null; a=new int [v.size]; for(i=0;i<v.size; i++){a[i]= v.a[i]; size=v.size;} return * this; необх скопировать один объект в др. При присваивании выполняется поэлементное копирование, т.е. после копирования объекты имеют одинаковое представление данных-членов класса.