Перегрузка функций-операторов 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Перегрузка функций-операторов



Пример: иллюстрирует перегрузку операторов для гипотетического класса с именем Z:

class Z{ public:

//четыре перегруженные ф-ции-//оператора

friend Z operator+(Z a, Z b);

friend Z operator-(Z a, Z b);

friend Z operator*(Z a, Z b);

friend Z operator/(Z a, Z b);

//... прочие открытые,

// защищенные и закрытые члены

};

В классе ZZ объявлены четыре перегруженные функции-оператора. (На практике в ZZ могут объявляться и другие открытые, защищенные и закрытые члены.) Имена функций — operator+(), operator-(), operator*0 и operator/().

Обычно нельзя использовать символы типа +, -, * или / в идентификаторах, однако для перегрузки операторов в C++ имя функции может состоять из слова operator и одного из символов, приведенных в табл. 4.1.

Таблица 4.1- Список операторов, которые могут быть перегружены

* / + - % ^ & |
~ ! , = < > <= >=
++ -- << >> == != && ||
*= /= %= ^= &= |= += -=
<<= >>= -> ->* [] () New delete

Операторы +, -, * и & могут перегружаться для бинарных и для унарных выражений.

Операторы., .*, :: и sizeof не могут перегружаться вообще.

Операторы =, (), [] и -> следует реализовать неста­тическими функциями-членами.

 

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

 

friend Z operator+ (Z a, Z b);

 

Функция объявляется дружественной классу, что дает функции operator+() доступ к закрытым и защи­щенным членам этого класса. Функция возвращает объекты типа Z (но может возвращать и любой другой тип), и этот результат можно присвоить другому объекту Z.

(Присваивание одного объекта другому создает несколько "скользких" моментов. Эта тема будет обсуждаться позднее в этой главе.)

Более важно то, что имя функции. operator+() идентифицирует функцию как метод, с помощью которого выражения, использующие оператор сложения, могут оперировать объектами класса. Предполагается, что функция operator+() складыва­ет два объекта способом, подходящим для класса Z.

 

operator+() — всего лишь имя функции.

Если назовем функцию именем fun() вместо operator(), то сможем употреб­лять операторы следующего вида:

fun(a, b);

где а и b — объекты типа Z.

 

Заменив fun на operator+, можно вызывать функцию перегруз­ки оператора следующим образом:

operator+(a, b);

// Аналогично fun(a, b)

 

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

как перегруженный оператор, функция operator+() может вызываться в выражениях, в которых использу­ется знак плюс.

Например, следующий оператор эквивалентен предыдущему вызову функции:

 

а + b;

// Аналогично operator+(a, b);!

 

Выражения а + b и operator+(a, b) выполняют одну и ту же работу и в точности генерируют один и тот же код.

Есть только одна причина использовать ту или иную форму - ясность.

Перегрузка операторов не прив­носит в C++ ничего такого, чего бы вы уже не знали. Это всего лишь позволит вам использовать объекты в выражениях, вместо того чтобы передавать их функции.

Работающий пример класса, в котором используются перегруженные операторы, поможет проиллюстриро­вать эти концепции.

В листинге 4.4 содержится класс, способный запоминать целые значения в виде строк.

С помощью перегруженных операторов программа может вычислять выражения, в которых складываются и вычитаются строки в виде эквивалентных им числовых значений.

 

ПРИМЕР 4.4. STROPS.CPP (функции перегруженных операторов)

#include <iostream.h>

#include <stdlib.h>

#include <string.h>

#include <conio.h>

class TStrOp {

private:

char value[12];

public:

TStrOp() { value[0] = '\0'; }

TStrOp(const char *s);

long GetValue(void) { return atoi(value); }

// дружественные функции, объявленные

//в строках 12—13, перегружают операторы

//сложения и вычитания для пары

//объектов класса TStrOp

friend long operator+(TStrOp a, TStrOp b);

friend long operator-(TStrOp a, TStrOp b); };

main() {

TStrOp a = "1234";

TStrOp b = "4321";

cout << "Value of a ==" <<a.GetValue();

cout << "\n Value of b == “" <<b.GetValue();

cout <<"\na + b + 6 == “"<< (a+b+6);

cout << "\na - b + 10 == “"<< (a-b+10);

getch();

return 0;

}

TStrOp::TStrOp(const char *s) {

strncpy(value, s, 11);

value[11] = 0; }

long operator+(TStrOp a, TStrOp b)

{

return (atoi(a.value) + atoi(b.value));

}

long operator-(TStrOp a, TStrOp b)

{

return (atol(a.value) - atol(b.value));

}

Запуск STROPS на выполнение приведет к следующим результатам:

Value of a == 1234

Value of b == 4321

a + b + 6 == 5561

a - ь + 10 == -3077

Перед тем как ознакомиться с классом и его функциями перегрузки операторов в программе, рассмотрим функцию mainO. В строках 18-19 объявляются два объекта типа TStrOp — а и b. Объекты инициализируют­ся символьными строками и могут быть реализованы также следующим образом:

TStrOp a("1234");

TStrOp b("4321");

Несмотря на то что со всей очевидностью эти объекты представляют собой строковые значения, выражения в строках 23 и 24 складывают и вычитают их непосредственным образом:

(а + Ь + 6)

(а - b + 10)

 

Обычно вы не можете использовать строки или объекты в подобных выражениях; перегрузка операторов расширяет знания C++ о том, объекты каких типов можно складывать и вычитать.

Две дружественные функции, объявленные в строках 12—13, перегружают операторы сложения и вычитания для пары объектов класса TStrOp.

Объявления сходны с теми, что пояснялись ранее в гипотетическом классе ZZ. Конечно,

в данном случае функция возвращает длинное целое.

Обычно функции перегрузки операторов име­ют тип класса (или ссылки на объект класса), объектами которого они оперируют, но это не обязательно. Функ­ции перегрузки операторов, равно как и другие функции, могут возвращать любые типы данных.

Рассмотрим реализацию перегруженных операторов в строках 35-43. Поскольку функции объявлены дру­жественными и не членами класса, их реализация vидентична реализации обычных функций в C++. Единст­венное отличие заключается в специальных именах функций — operator+ и operator-, что позволяет компиля­тору вычислять выражения, использующие операторы сложения и вычитания с объектами класса TStrOp.

Поскольку функции операторов — друзья, они имеют доступ к закрытым и защищенным членам объектов TStrOp. Этот факт позволяет функциям преобразовывать строки-значения в параметрах а и b в це­лое. Это преобразование осуществляется путем обращения к стандартной функции atoi (ASCII to int), прототип которой содержится в заголовочном файле STDLIB.H. Функции просто возвращают сумму или разницу преобразованных значений.

 

Перегрузка операторных функций-членов

Перегруженные функции могут быть членами класса, как это демонстрируется в примере 4.5. Эта про­грамма на STROPS.CPP (листинг 4.4), однако в ней иллюстрируется перегрузка операторов функ­циями-членами.

Листинг 4.5. STR0PS2.CPP (перегрузка операторов функциями-членами)

#include <iostream.h>

#include <stdlib.h>

#include <string.h>

#include <conio.h>

class TStrOp {

private:

char value[12];

public:

TStrOp() { value[0] = 0; }

TStrOp(const char *s);

long GetValue(void)

{ return atol(value); }

long operator+(TStrOp b);

long operator-(TStrOp b);

};

Main()

{

TStrOp a = "1234";

TStrOp b = "4321";

cout << "\nValue of a == " <<a.GetValue();

cout <<"\nValue of b == " <<b.GetValue();

cout <<"\na + b + 6 == "<< (a+b+6)<<"\n";

cout <<"\na - b + 10 == " << (a-b+10)<<"\n";

getch();

return 0;

}

TStrOp:: TStrOp(const char *s) {

strncpy(value, s, 11);

value[11] = 0;

}

long TStrOp::operator+(TStrOp b) {

return (atol(value) + atol(b.value));

}

long TStrOp::operator-(TStrOp b)

{ return (atol(value) - atol(b.value));

}

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

//Для сложения двух строковых //значений operator+() суммирует //длинные целые значения, //эквивалентные выражениям

// this->value и b.value.

Рассмотрим перегруженные операторные функции-члены, объявленные в строках 12-13 и реализованные в строках 32-33. Поскольку эти функции — члены класса TStrOp, они уже имеют доступ к защищенным и за­крытым членам класса, таким образом, не надо их указывать друзьями класса. Кроме того, эти функции-члены получают указатель this, ссылающийся на объект, для которого они были вызваны. Следовательно, функ­циям необходим всего лишь один параметр, а не два, как ранее. Для сложения двух строковых значений operator+() суммирует длинные целые значения, эквивалентные выражениям this->value и b.value.

Функциям-операторам и функциям-членам необходимо соответствующее число параметров. Вы не сможете объявить operator+О в строке 12 следующим образом:

long operator+(TStrOp a, TStrOp b); //???

Эта строка не скомпилируется, поскольку operator+О — член класса TStrOp и как функция-член получает указатель this, ссылающийся на объект класса. С учетом указателя this и аргументов а и b всего функция име­ет три параметра, а перегруженному бинарному оператору, подобному operator+О, необходимы только два. Для сложения двух объектов класса TStrOp функция operator+О суммирует *this.value и b.value (строка 37). Ей не нужен третий параметр. Функция-член operator-О также получает указатель this и, следовательно, нуж­дается только в одном аргументе для перегрузки бинарного оператора вычитания (строки 40-43).



Поделиться:


Последнее изменение этой страницы: 2016-08-01; просмотров: 197; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.135.202.224 (0.027 с.)