Тип_возвр_значения имя_класса :: operator #(список аргументов)
{ действия, выполняемые применительно к классу }; Вместо символа # ставится значок перегружаемого оператора. Следует отметить, что нельзя перегрузить триадный оператор ”?:.”, оператор ”sizeof” и оператор разрешения контекста ”::”. Функция operator должна быть либо компонентой класса, либо иметь хотя бы один аргумент типа ”объект класса” (за исключением при перегрузке операторов new и delete).Это позволит доопределить свойства операции, а не изменить их. При этом новое значение оператора будет иметь силу только для типов данных, определенных пользователем; для других выражений, использующих операнды стандартных типов, значение оператора останется прежним. Выражение a#b, имеющее первый операнд а стандартного типа данных, не может быть переопределено функцией operator, являющейся компонентом класса. Например, выражение a-4 может быть представлено как a.operator-(4), где а – объект некоторого типа. Выражение вида 4-a нельзя представить в виде 4.operator(a). Это может быть реализовано с использованием глобальных функций operator. Функция operator может быть вызвана так же, как и любая другая функция. Использование операции – лишь сокращенная форма вызова функции. Например, запись вида a=в-с; эквивалентна a=operator-(b,с).
Перегрузка бинарного оператора Функция operator для перегрузки (доопределения) бинарных операторов может быть описана двумя способами: - как компонента-функция класса с одним аргументом; - как глобальная функция (функция, описанная вне класса) с двумя аргументами. При перегрузке бинарного оператора # выражение a#b может быть представлено при первом способе как a.operator#(b) или как operator #(a,b) при втором способе перегрузки. Рассмотрим простой пример переопределения операторов *, =, > и == по отношению к объекту, содержащему декартовы координаты точки на плоскости. В примере использован первый способ перегрузки.
#include "iostream.h" Class dek_koord { int x,y; // декартовы координаты точки public: dek_koord(){}; dek_koord(int X,int Y): x(X),y(Y) {} dek_koord operator*(const dek_koord); dek_koord operator=(const dek_koord); dek_koord operator>(const dek_koord); int operator ==(const dek_koord); void see(); }; dek_koord dek_koord::operator*(dek_koord a) // перегрузка операции * { dek_koord tmp; // локальный объект tmp.x=x*a.x; tmp.y= y*a.y; return tmp; } dek_koord dek_koord::operator =(const dek_koord a) { x=a.x; // перегрузка операции = y=a.y; return *this; } dek_koord dek_koord::operator >(const dek_koord a) { if (x<a.x) x=a.x; // перегрузка операции > if (y<a.y) y=a.y; return *this; } int dek_koord::operator ==(const dek_koord a) // перегрузка операции == { if (x==a.x && y==a.y) return 0; // 0 – координаты равны if (x>a.x && y>a.y) return 1; // if (x<a.x && y<a.y) return -1; // else return 2; // неопределенность } void dek_koord::see() // функция просмотра содержимого объекта { cout << "координата х = " << x << endl; cout << "координата y = " << y << endl; } void main() { dek_koord A(1,2), B(3,4), C; int i; A.see(); B.see(); C=A*B; // вначале перегрузка операции * затем = C.see(); C=A>B; // компоненты объекта С принимают значение max от А и В C.see(); i=A==B; // i получает значение сравненияA==B (-1,0,1,2….) // cout << A==B << endl; // ошибка // error binary '<<': no operator defined which takes a right-hand operand // of type 'class dek_koord' (or there is no acceptable conversion) cout << (A==B) << endl; // верно } Результат работы программы: координата х = 1 координата y = 2 координата х = 3 координата y = 4 координата х = 3 координата y = 8 координата х = 3 координата y = 4 В приведенной выше программе функцию перегрузки оператора * можно изменить, например, следующим образом: dek_koord &dek_koord::operator*(const dek_koord &a) { x*=a.x; y*=a.y; return *this; } В этом примере функция operator* в качестве параметра получает ссылку на объект, стоящий в правой части выражения А*В, то есть на В. Ссылка – это второе имя (псевдоним) для одного и того же объекта. Более подробно ссылки будут рассмотрены позже. Функция operator* при вызове получает скрытый указатель на объект А и модифицирует неявные параметры (компоненты-данные объекта А – х и у). Возвращается значение по адресу this, то есть объект А. Возвращать ссылку на объект необходимо для реализации выражения вида A*B*C.
Следует отметить, что если в описании класса dek_koord присутствуют объявления двух функций перегрузки операции *: class dek_koord {... dek_koord operator*(const dek_koord); dek_koord &operator*(const dek_koord &); ... }; то возникает ошибка. Аналогично ошибка будет, если одна из функций является компонентой класса, а другая глобальной функцией. Если возвращаемое значение функции operator является ссылкой, то в этом случае возвращаемое значение не может быть автоматической или статической локальной переменной. Рассмотрим фрагмент программы, в которой функция operator* является глобальной. Class dek_koord { int x,y; // декартовы координаты точки public: ... int read_x(); // возвращает компоненту x int read_y(); // возвращает компоненту y void write_x(int); // модифицирует компоненту x void write_y(int); // модифицирует компоненту y ... }; int dek_koord::read_x(){return x;} int dek_koord::read_y(){return y;} void dek_koord::write_x(int a){x=a;} void dek_koord::write_y(int a){y=a;} dek_koord operator*(dek_koord a,dek_koord b) // перегрузка операции * { dek_koord tmp; // функция operator - глобальная tmp.write_x(a.read_x()*b.read_x()); tmp.write_y(a.read_y()*b.read_y()); return tmp; } В глобальной функции operator* доступ к private данным локального объекта tmp возможен через public функции этого объекта, либо данные класса должны иметь атрибут public, что не отвечает принципу инкапсуляции. Кроме того, если функция operator является friend-функцией некоторого класса, то она имеет доступ к private компонентам этого класса. Это будет рассмотрено несколько позже. Ниже приведен пример еще одной программы перегрузки оператора ”-“ для использования его при вычитании из одной строки другой. #include <iostream.h> #include <string.h> Class String { char str[80]; // локальная компонента public: // глобальные компоненты void init (char *s); // функция инициализации int operator - (String s_new); // прототип функции operator } my_string1, my_string2; // описание двух объектов класса String void String::init (char *s) // функция обеспечивает копирование // строки аргумента(s) в строку-компоненту { strcpy(str,s);} // (str) класса String int String::operator - (String s_new) // перегрузка оператора – (вычитания
// строк) { for (int i=0; str[i]==s_new.str[i]; i++) if (!str[i]) return 0; return str[i] - s_new.str[i]; } void main(void) { char s1[51], s2[51]; cout <<"Введите первую строку не более 80 символов:" <<endl; cin >>s1; cout<<" Введите вторую строку не более 80 символов "<<endl; cin>>s2; my_string1.init(s1); //инициализация объекта my_string1 my_string2.init(s2); //инициализация объекта my_string2 cout <<"\nString1 - String2 = "; // вывод на экран разности двух строк cout << my_string1 - my_string2 << endl; } Результат работы программы: Введите первую строку не более 80 символов: overload Введите вторую строку не более 80 символов function String1 – String2 = 9 При перегрузке бинарного оператора с использованием компоненты-функции ей передается в качестве параметра только один аргумент. Второй аргумент получается посредством использования неявного указателя this на объект, компоненты которого модифицируются.
Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|