Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
недостающая теория.doc
Скачиваний:
8
Добавлен:
22.09.2019
Размер:
619.01 Кб
Скачать

5.2.2. Перегрузка унарного оператора

При перегрузке унарной операции функция operator не имеет параметров. Как и в предыдущем случае, модифицируемый объект передается в функцию-operator неявным образом, используя указатель this.

Унарный оператор, как и бинарный, может быть перегружен двумя способами:

  • как компонента-функция без аргументов;

  • как глобальная функция с одним аргументом.

Как известно, унарный оператор может быть префиксным и постфиксным. Для любого префиксного унарного оператора выражение #a может быть представлено при первом способе как a.operator#(), а при втором как #operator(a).

При перегрузке унарного оператора, используемого в постфиксной форме, выражение вида a# может быть представлено при первом способе как a.operator#(int) или как operator#(a,int) при втором способе. При этом аргумент типа int не существует и используется для отличия префиксной и постфиксной форм при перегрузке.

Ниже приведен пример программы перегрузки оператора ++ и реализации множественного присваивания. Для перегрузки унарного оператора ++, предшествующего оператору ++i, вызывается функция operator ++(). В случае если оператор ++ следует за операндом i++, то вызывается функция operator++(int x), где х принимает значение 0.

#include «iostream»

using namespace std;

class dek_koord

{ int x,y; // декартовы координаты точки

public:

dek_koord(){};

dek_koord(int X,int Y): x(X),y(Y) {}

void operator++();

void operator++(int);

dek_koord operator=(dek_koord);

void see();

};

void dek_koord::operator++() // перегрузка операции ++A

{ x++;}

void dek_koord::operator++(int) // перегрузка операции A++

{ y++;}

dek_koord dek_koord::operator =(dek_koord a)

{ x=a.x; // перегрузка операции =

y=a.y;

return *this;

}

void dek_koord::see()

{ cout << "координата х = " << x << endl;

cout << "координата y = " << y << endl;

}

int main()

{ dek_koord A(1,2), B, C;

A.see();

A++; // увеличение значения компоненты х объекта А

A.see(); // просмотр содержимого объекта А

++A; // увеличение значения компоненты у объекта А

A.see(); // просмотр содержимого объекта А

C=B=A; // множественное присваивание

B.see();

C.see();

}

Результат работы программы:

координата х = 1

координата y = 2

координата х = 1

координата y = 3

координата х = 2

координата y = 3

координата х = 2

координата y = 3

координата х = 2

координата y = 3

5.2.3. Дружественная функция operator

Функция operator может быть не только членом класса, но и friend-функцией этого класса. Как было отмечено ранее, friend-функции, не являясь компонентами класса, не имеют неявного указателя this. Следовательно, при перегрузке унарных операторов в функцию operator передается один, а бинарных – два аргумента. Необходимо отметить, что операторы: =, (), [] и -> не могут быть перегружены с помощью friend-функции operator.

#include <iostream>

using namespace std;

class dek_koord

{ int x,y; // декартовы координаты точки

public:

dek_koord(){};

dek_koord(int X,int Y): x(X),y(Y) {}

friend dek_koord operator*(int,dek_koord);

friend dek_koord operator*(dek_koord,int);

dek_koord operator=(dek_koord);

void see();

};

dek_koord operator*(int k,dek_koord dk) // перегрузка операции int *A

{ dk.x*=k;

dk.y*=k;

return dk;

}

dek_koord operator*(dek_koord dk,int k) // перегрузка операции A*int

{ dk.x*=k;

dk.y*=k;

return dk;

}

dek_koord dek_koord::operator=(dek_koord dk)

{ x=dk.x;

y=dk.y;

return *this;

}

void dek_koord::see()

{ cout << "координаты (х,y) точки = " << x<<’ ’ <<y<< endl;

}

int main()

{ dek_koord A(1,2), B;

A.see();

B=A*2; // увеличение значения объекта А в 2 раза

B.see(); // просмотр содержимого объекта B

}

Результат работы программы:

координаты (х,y) точки = 1 2

координаты (х,y) точки = 2 4

5.2.4. Особенности перегрузки операции =

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

Конструктор выполняет все необходимые действия при вызове функции и копировании содержимого объекта в стек (из стека). Вызов конструктора копирования осуществляется при обращении к функции и передаче в нее в качестве параметра объекта (объектов), а также возврата значения (объекта) из функции.

#include <iostream>

using namespace std;

#include "string.h"

class string

{ char *str; // символьная строка

int size; // длина символьной строки

public:

string(); // конструктор по умолчанию

string(int n,char *s); // конструктор с параметрами

string(const string &); // конструктор копирования

~string(); // деструктор

friend string operator+(string, const string);

string &operator=(const string &);

void see();

};

string::string(){size=0; str=NULL;}; // конструктор по умолчанию

string::string(int n,char *s) // конструктор с параметрами

{ str=new char[size=n>=(strlen(s)+1)? n : strlen(s)+1];

strcpy(str,s);

}

string::string(const string &a) // описание конструктора копирования

{ str=new char[a.size+1]; // выделяем память под this->str (+1 под ’\0’)

strcpy(str,a.str); // копирование строки

size=strlen(str)+1;

}

string::~string(){ if(str) delete [] str;}

string operator+(string s1, const string s2) // перегрузка операции +

{ string ss;

if(!ss.str) ss.str=new char[ss.size=strlen(s1.str)+strlen(s2.str)+2];

for(int i=0; ss.str[i]=s1.str[i]; i++); // перезапись символа ’\0’

ss.str[i]=' '; // удаление ’\0’

for(int j=0; ss.str[i+1]=s2.str[j]; i++,j++); // дозапись второй строки

return ss;

}

string &string::operator =(const string &st) // перегрузка операции =

{ if(this!=&st) // проверка, не копирование ли объекта в себя

{ delete str; // освобождаем память старой строки

str=new char[size=st.size];// выделяем память под новую строку

strcpy(str,st.str);

}

return *this;

}

void string::see()

{ cout << this->str << endl;

}

int main()

{ string s1(10,"язык"), s2(30,"программирования"), s3(30," ");

s1.see();

s2.see();

string s4=s1; // это только вызов конструктора копирования

s4.see();

string s5(s1); // прямой вызов конструктора копирования

s5.see();

s1+s2; // перегрузка + (вызов функции operator +)

s1.see();

s3=s2; // перегрузка = (вызов функции operator =)

s3.see();

s3=s1+s2; //перегрузка операции + , затем операции =

s3.see();

return 0;

}

Результаты работы программы:

язык

программирования

язык

язык

программирования

язык программирования

Инструкция string s4=s1 только вызывает конструктор копирования для объекта s4. В инструкции string s5(s1) выполняется прямой вызов конструктора копирования для объекта s5. Выполнение инструкции s1+s2 приводит к двум вызовам конструктора копирования (вначале для копирования в стек объекта s2, затем s1). После этого выполняется вызов функции operator+ для инструкции s1+s2. При выходе из функции (инструкция return ss) вновь выполняется вызов конструктора копирования. При выполнении инструкции s3=s2 конструктор копирования для копирования объекта s2 в стек не вызывался, так как параметр в operator= передан (и возвращен) по ссылке.