Объектно-ориентированное программирование — Перегрузка операций

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

Операции могут быть перегружены с помощью составных и дружественных функций. Имя функции, соответствующей операции, получается добавлением символа операции к слову operator. Например,

class Bits

{

char *b;

int size;

public:

Bits operator+(const Bits&); // сложение

Bits operator-(const Bits&); // вычитание

Bits operator-(); // унарный минус

Friend Bits& operator^(const Bits&, const Bits&); //XOR

};

Если операция определяется с помощью составной функции, то эта функция имеет на один аргумент меньше, чем в том случае, когда операция определяется с помощью дружественной функции. Для составной функции первый аргумент предполагается равным *this. Например, для класса строки операцию сравнения относительно лексикографического (алфавитного) порядка можно определить с помощью приведённой ниже составной функции:

#include

class String

{

char *s;

int len;

public:

int operator<(String st)

{

return strcmp(s,st,s)<0;

}

};

То же самое с помощью дружественной функции определяется следующим образом

#include

class String

{

char *s;

int len;

public:

friend int operator<(String, String);

};

operator<(String str1, String str2)

{

return strcmp(str1.s, str2.s)<0;

}

Перегрузка операций позволяет определить для классов значения любых операций, исключая “.”, ”::”, ”.*”, ”?:”, sizeof. Отсюда вытекает, что разрешено определять операции для класса, символы которых равны:

newdelete

+ — * / % ^ &

| ~ ! = +=

-= *= /= %= ^= &= |=

= == != <=

>= && || ++ -- () []

-> ->*

Здесь стандартная операция ->* обозначает косвенное обращение к элементу класса (элементу структуры) через указатель на объект и указатель на этот элемент,

например,

class C

{

int *d;

friend int f(C *p);

};

int f(C *p) {return p->*d;}

Аналогично, операция .* обозначает прямое обращение к элементу класса по имени объекта и указателю на элемент.

Приведем пример перегрузки операции индексации [], обычно используемую для возвращения ссылки, что позволяет применять ее в операции присваивания с обеих сторон.

Пример. Пусть класс определен как строка символов. Определим операцию индексации, позволяющую читать и записывать i-й символ строки:

#include

#include

#include

// Класс строка

class String

{

// Закрытые элементы

char *s; // Сама строка

int len; // Её длина

public: // Общедоступные элементы

// Перегрузка операции []

char& operator[](int pos)

{

return s[pos];

}

// Инициализация строки

void init(char *s)

{

len=strlen(s); // Определение длины

String::s=new char[len+1]; // Выделение памяти под строку

strcpy(String::s, s); // Присваивание

}

// Вывод строки на экран

void show()

{

cout<

}

};

void main()

{

clrscr(); // Очистка экрана

String a; // Создаём строку

a.init("abc"); // Инициализируем её

cout<<"Начальное содержимое строки: ";

a.show(); // Выводим строку на экран

a[1]='c';

cout<<"Содержимое строки после операции a[1]=\'c\': ";

a.show(); // Выводим строку на экран

a[0]='b';

cout<<"Содержимое строки после операции a[0]=\'b\': ";

a.show(); // Выводим строку на экран

cout<<"Содержимое строки после операции a[0]=a[2]: ";

a[0]=a[2];

a.show(); // Выводим строку на экран

getch(); // Ожидание нажатия клавиши

}

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

Начальное содержимое строки: abc

Содержимое строки после операции a[1]='c': acc

Содержимое строки после операции a[0]='b': bcc

Содержимое строки после операции a[0]=a[2]: ccc

Вызов операции возвращает адрес a[i]. Присваивание a[i]=x записывает в этот адрес x.

Операции ++ и -- могут быть как префиксными и записываться ++x или --x, так и постфиксными — x++, x--. Если определять префиксные операции через составные функции, то следует указать обычным образом тип возвращаемого значения. Например,

class A

{

A& operator++();

A& operator--();

};

Префиксные операции ++ и -- можно определить как дружественные функции от одной переменной, представляющие собой ссылку на объект данного класса. Например,

class A

{

friend A& operator++(A&);

friend A& operator--(A&);

};

Постфиксные операции ++ и -- определяются с помощью функций, имеющих дополнительный аргумент типа int, который на самом деле не используется. Например:

class A

{

int x;

public:

void operator++() { x=x+2;}

void operator++(int) { x=x+1;}

};

void main()

{

A b;

b++; // b.x увеличили на 1

++b; // b.x увеличили на 2

}

Вы здесь: Главная Информатика Программирование Объектно-ориентированное программирование