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

Void print(const Week &d) // вывод на экран названий дней недели

{

string Days[7] = {"Sunday", "Monday", "Tuesday",

"Wednesday", "Thursday", "Friday", "Saturday" };

cout << Days[d] << endl;

}

Week m = sat; // m - суббота

print(m+l); // выводит 'Sunday'

print(2+m); // выводит 'Monday'

print(operator+(m,l)): // выводит 'Sunday'

print(operator+(2,m)): // выводит 'Monday'

m++; // вызов постфиксной формы, m == sun

print(m); // выводит 'Sunday'

print(++m); // выводит 'Monday'

print(operator++(m)); // префиксная форма, выводит 'Tuesday'

print(operator++(m,u)): // постфиксная форма, выводит 'Tuesday'

print(m); // выводит 'Wednesday'

При перегрузке операции внешней для класса функцией поля должны быть открыты или класс должен предоставлять методы get() и set () для получения и изменения значений полей.

Пример перегрузки операции сложения для класса независимой функцией.

struct Fraction

{

int num;

Int denum; // поля - открыты

Void reduce(); // метод - открыт

};

Fraction operator+(const Fraction &l, const Fraction &r)

{

Fraction t;

// (a,b)+(c,d)=(ad+bc,bd)

t.denum = l.denum*r.denum; // знаменатель результата

t.num = l.num*r.denum+r.num*l.denum; // числитель результата

t.reduce(); // сокращение

return t;

}

Fraction a, b, c;

// ...

a = b + с; // инфиксная форма

a = operator+(b,c); // функциональная форма

Перегрузка операций методами класса

У методов один параметр – текущий объект – определен по умолчанию. Унарные операции выполняются для текущего объекта, который и является единственным аргументом. Поэтому унарные операции, перегружаемые как методы класса, не имеют параметров. Прототип унарной операции, реализованной как метод класса, выглядит так:

тип operator@();

где @ – символ операции. Возвращаемое значение может быть любого типа, в том числе и определяемого класса. Операция может возвращать значение, ссылку или указатель на объект. Разрешается указывать void на месте типа возвращаемого значения.

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

Префиксная форма инкремента (и декремента) должна иметь прототип

тип& operator@();

Постфиксная операция инкремента (и декремента) должна иметь прототип

тип operator@(int);

Тип – это «имя_класса», в котором определяется операция.

Прототип бинарной операции имеет один аргумент и выглядит таким образом:

тип operator@(параметр);

Параметры разрешается передавать любым удобным нам способом: по значению, по ссылке или по указателю. Возвращать метод-операция тоже может значение, указатель или ссылку на объект, в том числе и своего класса. Разрешается указывать void на месте типа возвращаемого значения.

При реализации метода-операции вне класса требуется в заголовке обычным образом указывать префикс-имя класса:

тип класс::operator@() // унарная операция

тип класс::operator@(параметр) // бинарная операция

Вызов унарной операции для объекта имеет форму

@объект

объект@

в зависимости от того, какой вид операции используется – префиксный или постфиксный. Функциональный вызов для префиксной операции имеет форму

объект.operator@()

Для постфиксной операции в функциональной форме вызова нужно задавать фиктивный аргумент:

объект.operator@(0)

Функциональная форма вызова для бинарной операции, определенной как метод класса, выглядит так:

объект.operator@(аргумент)

Инфиксная форма

объект @ аргумент

является сокращением функциональной.

Операции присваивания являются бинарными операциями, поэтому должны иметь один аргумент. Если операция присваивания operator= не реализуется явным образом, она создается автоматически по умолчанию. Для любого класса автоматически создаваемая операция присваивания имеет прототип

класс& operator=(const класс &r)

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

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

Money& Money::operator+=(const Money &b)

Повторное использование можно явным образом запретить, если возвращать константную ссылку, например

const Moneys Money::operator+=(const Money &b)

Модификатор const запрещает дальнейшую модификацию результата.

Функции-друзья класса

Любая внешняя функция, определенная как «друг» класса, имеет неограниченный доступ к любым элементам класса, в том числе и к закрытым. Для того чтобы внешняя функция стала другом класса, необходимо в интерфейсе класса задать ее прототип, добавив впереди слово friend, например

friend Money operator*(const long double &a, const Money &b);

При реализации функции слово friend писать запрещается. Не указывается также и префикс класса.

Рекомендуемые формы перегрузки операций для класса приведены в таблице 1. В частности, операции ввода/вывода operator>> и operator<< практически всегда реализуются как внешние дружественные функции. Например, для класса Two с двумя полями х и у целого типа эти функции могут выглядеть так:

ostream& operator<<(ostream& t, const Two &r)

{ return (t << '(' << r.x << '.' << r.y << ')'); }

istream& operator>>(istream& t, Two &r)

{ t >> r.x >> r.y; return t; )

Пример перегрузки операций методами класса и дружественными функциями

class F

{

int f;

int m;

public:

F(int t, int r = 0):f(t),m(r)// конструктор

{ }

F& operator++() // префиксный инкремент

{ f++; return *this; }

F operator++(int) // постфиксный инкремент

{F t= *this; f++; return t; }

F& operator+=(const F& r) // сложение с присваивание

{ f+=r.f; m+=r.m; return *this; }

// дружественные функции

friend F operator+(const F &l, const F &r);

friend ostream& operator<<(ostream& t, const F &r);

friend istream& operator>>(istream& t, F &r);

};

// реализация дружественных функций

F operator+(const F &l, const F &r)

{ F t = l; t+=r; return t; }

// дружественные функции ввода/вывода

ostream& operator«(ostream& t, const F &r)

{ return (t << r.f << '/' << r.m); }

istream& operator>>(istream& t, F &r)

{ t >> r.f >> r.m; return t; }

Таблица 1

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

Операция

Рекомендуемая форма перегрузки

Все унарные операции

Метод класса

- [] 0 -> *

Обязательно метод класса

+= -= *= /= %= &=. |= ^= <<= >>=

Метод класса

Остальные бинарные операции

Внешняя функция-друг

В описание класса добавляем конструкторы:

class P_number_class {

char number[200]; // число

unsigned int scale_of_notation; // система счисления

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