Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Lutsik_Yu_A_Obektno_orientir_programmir_na_yaz.pdf
Скачиваний:
63
Добавлен:
11.05.2015
Размер:
4.33 Mб
Скачать

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

язык

язык

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

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

s1+s2. При выходе из функции (инструкция return ss) вновь выполняется вызов

 

 

И

конструктора копирования. При выполнении инструкции s3=s2 конструктор ко-

пирования для копирования объекта s2 в стек не вызывался, так как параметрРв

operator= передан (и возвращен) по ссылке.

У

5.2.5. Перегрузка оператора []

Г

 

 

 

Как было отмечено выше, функция operator может быть с успехом ис- пользована для доопределения операторов С++ (в основном арифметические,

 

 

 

 

 

 

 

а

логические и операторы отношения). В то же время в С++ существуют некото-

рые операторы, не входящие в число перечисленныхБ, но которые полезно пере-

 

 

 

 

 

 

к

гружать. К ним относится оператор []. Его необходимо перегружать с помощью

 

 

 

 

 

 

е

 

компоненты-функции, использование friend-функции запрещено. Общая

форма функции operator[]() имеет вид

 

 

тип_возвр_значения имя класса::operator [](int i)

{

тело функции}

 

но

 

 

 

 

 

 

 

 

 

Параметр функции не бяза ельно должен иметь тип int , но он использо-

 

 

 

и

 

 

ван, так как operator[] в

с внтм применяется для индексации. Рассмотрим

пример программы с с

 

ьзованием перегрузки операции []:

#include <iostream>

 

 

 

 

 

 

б

 

 

 

 

 

using namespace std;

 

 

 

 

class massiv пол

 

 

 

{

float f[3];

 

 

 

 

 

 

public:

 

 

 

 

 

 

 

massiv(floatи i,float j,float k){f[0]=i; f[1]=j; f[2]=k;}

 

float operator[](int i)

 

 

Б{ return f[i];} // перегрузка оператора []

};

int main()

{massiv ff(1,2,3); double f;

int i;

114

cout << "введите номер индекса "; cin >> i;

cout <<"f["<< i <<" ]= " << ff[i] << endl; return 0;

}

В примере перегруженная функция operator[]() возвращает величину эле- мента массива, индекс которого передан в функцию в качестве параметра. Дан-

ная программа при небольшой модификации может позволить использовать оператор[] как справа, так и слева от оператора присваивания. Для этого необ- ходимо, чтобы функция operator[]() возвращала не элемент, а ссылку на него.

 

#include <iostream>

 

 

 

 

Р

 

using namespace std;

 

 

 

 

 

class massiv

 

 

 

 

 

 

 

 

 

 

И

 

{ float f[3];

 

 

 

 

 

public:

 

 

 

 

 

massiv(float i,float j,float k){f[0]=i; f[1]=j; f[2]=k;}У

 

 

float &operator[](int i) // перегрузка оператора []

 

 

{ if(i<0 || i>2)

 

 

Г

 

 

 

// провер на выход за границы массива

 

{ cout << “Выход за пределы м ссива”<<endl;

 

 

 

exit(1);

 

 

Б

 

 

 

 

ка

 

 

 

}

 

 

 

 

 

return f[i];

 

 

 

 

}

 

к

 

 

 

 

 

е

 

 

 

 

 

};

 

 

 

 

 

 

int main()

 

т

 

 

 

 

 

{ massiv ff(1,2,3);

 

 

 

 

 

int i;

 

 

 

 

 

 

cout <<и"введоте номер индекса ";

 

 

 

 

cin >> i;

 

 

 

 

 

 

 

cout <<"f["<< i <<" ]= " << ff[i] << endl;

 

 

 

ff[i]=5;л// если функция operator не возвращает ссылку,то компиля-

 

б

// тор выдает ошибку =' : left operand must be l-value

 

 

 

 

 

 

 

 

cout <<"f["<< i <<" ]= " << ff[i] << endl;

 

 

иreturn 0;

 

 

 

 

 

 

Б

}

 

 

 

 

 

 

Рассмотрим случай, когда функция operator возвращает не ссылку, а ука-

затель на модифицируемое значение. Внесем некоторые изменения в рассмот- ренную выше программу.

class massiv

{ float f[3]; public:

115

. . .

float *operator[](int i) // перегрузка оператора []

{. . .

return &f[i];

}

};

 

 

 

 

 

 

 

 

 

 

 

 

 

int main()

 

 

 

 

 

 

 

 

 

 

 

 

{ massiv ff(1,2,3);

 

 

 

 

 

 

 

 

 

Р

. . .

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

*ff[i]=5; //

функция operator возвращает указатель

 

И

cout <<"f["<< i <<" ]= " << *ff[i] << endl;

 

 

 

 

 

 

return 0;

 

 

 

 

 

 

 

 

 

У

 

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

В приведенном примере создается ложное впечатление, что ff является

 

 

 

 

 

 

 

 

 

 

Г

 

 

вектором указателей. Поэтому использование ссылки представляется более

предпочтительным.

 

 

 

 

 

 

 

Б

 

 

 

Приведем еще один пример программы, использующей перегрузку

operator[].

 

 

 

 

 

 

 

 

а

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

// перегрузка функции operator[] на примере вычисления n!

 

 

#include <iostream>

 

 

 

к

 

 

 

 

 

 

 

 

 

 

 

 

 

using namespace std;

 

 

 

 

 

 

 

 

 

#include "values.h"

 

// для опр д л ния онстанты MAXLONG

class fact

 

 

 

 

т

 

 

 

 

 

 

{ long l;

 

 

 

о

е

 

 

 

 

 

public:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

long operator[](int);

// перегрузка оператора []

 

 

 

};

 

л

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

long fact::operator[](int n)

 

 

 

 

 

 

 

 

{ long l;

б

и

//выбор буквы из уменьшаемой строки

 

for (int i=0; i<=n; i++)

 

и

 

 

 

 

 

 

 

 

 

 

 

 

if(l>MAXLONG/i)

 

 

 

 

 

 

 

 

 

cerr<<"ОШИБКА факториал числа "<<n<<" больше "<<MAXLONG;

Б

 

 

 

 

 

 

 

 

 

 

 

 

 

else l*=i; return l;

}

int main()

{fact f; int i,k;

cout << "введите число k для нахождения факториала" cin >> k;

for (i=1; i<=k; i++)

116

cout << i <<"! = " << f[i] << endl; return 0;

}

5.2.6. Перегрузка оператора ()

Оператор вызова функции можно доопределить, как и любой другой опе- ратор. Как и в предыдущем случае, оператор () необходимо перегружать только с помощью компоненты-функции, использование friend-функции запрещено.

Общая форма функции operator()() имеет вид

 

Р

 

 

 

 

 

 

 

 

 

 

 

 

тип_возвр_значения имя_класса::operator ()(список_аргументов)

 

{

тело функции}

 

 

 

 

 

 

 

#include <iostream>

 

 

 

У

 

 

using namespace std;

 

 

 

 

И

 

class matr

 

 

 

 

 

Г

 

{

 

int **m,a,b;

 

 

 

 

 

 

 

public:

 

 

 

 

 

 

 

 

 

 

matr(int,int);

 

 

 

 

 

 

 

 

~matr();

 

 

 

 

а

 

 

 

 

 

 

 

 

// перегрузкаБоператора ()

 

 

 

 

int operator()(int,int);

 

 

 

 

 

int operator()(int);

к

 

 

 

 

 

 

// перегрузка оператора ()

 

 

};

 

 

 

е

 

 

 

 

 

 

 

 

 

 

 

 

 

 

matr::matr(int i,int j): a(i),b(j)

// онструктор

 

 

 

{

i=0;

 

т

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

m=new int *[a];

 

 

 

 

 

 

 

 

 

 

о

 

 

 

 

 

 

 

 

for(int k=0; k<a; k++)

 

 

 

 

 

 

 

}

и

 

 

 

 

 

 

 

 

 

{

*(m+k)=new int[b];

 

 

 

 

 

 

 

 

for(int n=0; n<b; n++)

 

 

 

 

 

 

 

 

л

 

 

 

 

// заполнение m числами 0,1,2,3, …a*b

 

 

 

*(*(m+k)+n)=i++;

 

 

 

}

 

 

 

 

 

 

 

 

 

 

и

 

 

 

 

 

// деструктор

 

 

Б

matr::~matr()

 

 

 

 

 

б{ for(int k=0; k<a; k++)

 

 

 

 

 

 

 

 

 

 

 

 

 

delete [] m[k];

 

 

 

// освобождение памяти для k-й строки

 

 

delete [] m;

 

 

 

 

// освобождение памяти для всего массива

 

}

 

 

 

 

 

 

// указателей m

 

 

 

int matr::operator()(int i,int j)

 

 

 

 

 

{ if (i<0 || i>=a || j<0 || j>=b)

 

 

 

 

 

 

 

{ cerr<<"выход за пределы матрицы ";

 

 

 

 

 

return m[0][0];

// например, при этом возврат m[0][0]

 

 

}

 

 

 

 

 

 

 

 

 

 

return m[i][j];

 

// возврат требуемого элемента

 

117

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]