Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции по С++ глава 5.doc
Скачиваний:
3
Добавлен:
05.11.2018
Размер:
166.91 Кб
Скачать

5.1.1. Определение дополнительных функций-операторов

Подобно другим функциям языка C++, функции-операторы могут быть перегружены. При этом есть несколько способов вызова операторов. Например, с помощью оператора "+" можно сложить объект класса CCurrency с константой типа int или long. (В определенной выше функции предполагается, что оба операнда являются объектами класса CCurrency.) Для этого в класс CCurrency нужно добавить следующую функцию.

CCurrency operator+ (long Dol)

{

return CCurtency (Dollars + Dol, Cents);

}

Включение этой функции позволит использовать оператор «+» следующим образом.

CCurrency Advertising (235, 42);

// ...

Advertising+ = 100;

Компилятор будет интерпретировать выражение Advertising + 100 как

Advertising.operator+ (100)

и, следовательно, вызывать вновь определенную версию функции operator+. Тем не менее, целочисленную константу нельзя поставить первой, так как компилятор будет интерпретировать выражение 100 + Advertising как

100.operator+ (Advertising) // бессмысленно!

Чтобы обойти это ограничение, можно написать функцию-оператор, которая не является членом класса, но первый параметр которой имеет тип long.

// определяется глобально:

CCurrency operator+ (long Dol, const CCurrency SCurr)

{

return CCurrency (Dol + Curr.Dollars, Curr.Cents);

}

Но при использовании этой функции также могут возникнуть проблемы. Так как она не является функцией-членом класса CCurrency, то не имеет доступа к закрытым переменным этого класса (а именно, к Dollars и Cents). Для получения такого доступа функцию нужно сделать дружественной классу CCurrency, объявив ее внутри определения CCurrency с использованием спецификатора friend.

class CCurrency

{

// другие объявления ...

friend CCurrency operator+ (long Dol, const CCurrency &Curr);

// другие объявления ...

};

Даже если дружественная функция не является функцией-членом класса, она имеет доступ как к закрытым, так и к защищенным членам класса, который объявляет ее дружественной.

Когда такая функция-оператор определена, операцию сложения можно применить следующим образом.

CCurrency Advertising (235, 42);

// ...

Advertising = 100 + Advertising;

Теперь компилятор проинтерпретирует выражение 100 + Advertising как

operator+ (100, Advertising)

и, следовательно, вызовет дружественную версию функции-оператора.

Заметим: можно сделать дружественными две первые версии функции operator+, не определяя их как функции-члены класса (хотя особенного преимущества это не дает).

friend CCurrency operator+ (const CCurrency &Curr1,

const CCurrency &Curr2);

friend CCurrency operator+ (const CCurrency &Curr, long Dol);

Функция, перегружающая оператор и не являющаяся методом класса, должна иметь хотя бы один параметр – объект класса. Следовательно, функцию-оператор нельзя использовать для изменения стандартного смысла операторов в выражении, содержащем только данные встроенных типов.

Дружественные классы

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

class A

{

// ...

friend class FriendOfA;

// ...

};

Благодаря такому объявлению любая функция-член класса FriendOfA имеет доступ к закрытым и защищенным членам класса А.

Ниже приведено полное описание класса CCurrency вместе с функцией, не являющейся его членом.

#include <iostream.h>

class CCurrency

{

private:

long Dollars;

int Cents;

public:

CCurrency ()

{

Dollars = Cents = 0;

}

CCurrency (long Del, int Cen)

{

SetAmount (Dolf Cen);

}

void GetAmount (long *PDol, int *PCen}

{

*PDol = Dollars;

*PCen = Cents;

}

void PrintAmount { )

{

cout.fill 'O');

cout.width (1) ;

cout << '$' << Dollars << '.';

cout.width (2) ;

cout << Cents << '\n';

}

void SetAmount (long Dol, int Cen)

{

// проверка суммы центов, которая превышает 100:

Dollars = Dol +• Cen / 100;

Cents = Cen % 100;

}

CCurrency operator+ (const CCurrency &Curr)

{

return CCurrency (Dollars + Curr.Dollars, Cents + Curr.Cents);

}

CCurrency operators- (long Dol)

{

return CCurrency (Dollars + Dol, Cents);

}

friend CCurrency operator+ (long Dol, const CCurrency &Curr);

};

CCurrency operator+ (long Dol, const CCurrency &Curr)

{

return CCurrency (Dol + Curr.Dollars, Curr.Cents);

}

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

void main()

{

CCurrency Advertising (235, 42);

CCurrency Rent (823, 68);

CCurrency Entertainment (1024, 32);

CCurrency Overhead;

Overhead = Advertising + Rent + Entertainment;

Overhead.PrintAmount ();

Overhead = Overhead + 100;

Overhead.PrintAmount ();

Overhead =100 + Overhead;

Overhead.PrintAmount ();

}

На печать будут выведены значения.

$2083.42

$2183.42

$2283.42

Таким образом, определение трех версий функций-операторов дает возможность применить операцию сложения к двум объектам – объекту и константе, а также к константе и объекту. Четвертая возможная комбинация из двух констант дает стандартную операцию сложения. Далее в параграфе «Конструкторы преобразования» рассмотрена технология создания специального конструктора, исклю­чающего две версии функции operator+ из класса CCurrency.

Усовершенствование класса CCurrency

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

При определении таких функций избегайте преобразований сумм долларов и центов в одно значение типа long, хранящееся как общее количество центов. Это упрощает выполнение арифметических действий, но повышает вероятность переполнения и уменьшает максимальное значение суммы долларов.