Здавалка
Главная | Обратная связь

Перегрузка инкремента и декремента.



В прошлом уроке мы с вами разбирали перегрузку операторов и рассматривали пример класса, реализующего работу со строкой. В этом классе была использованна перегрузка бинарных операторов "=" и "+". Однако, нам с вами было бы неплохо рассмотреть перегрузку и унарных операторов. В частности, инкремента и декремента. Кроме свойства унарности, каждый из этих операторов обладает двумя формами, а это при их перегрузке имеет большое значение.

Следует отметить, что в начальных версиях языка C++ при перегрузке операций ++ и -- не делалось различия между постфиксной и префиксной формами. Например:

#include <iostream>using namespace std; class Digit{ // Целое число. int N; public: // Конструктор c параметром Digit(int n) { N = n; } // функция для показа числа на экран void display() { cout << "\nDigit: N = " << N << "\n"; } // Компонентная функция (форма не различается): Digit& operator -- () { // Уменьшаем содержимое объекта // в десять раз и возвращаем его // на место вызова оператора N /= 10; return *this; } };void main(){ // создаем объект Z именно с ним // мы и будем экспериментировать Digit Z(100); // показ объекта в первозданном виде cout<<"\nObject Z (before):\n"; Z.display(); cout<<"\n-----------------\n"; // присваиваем объекту Pref выражение // с префиксной формой (в данном случае // сначала изменится Z, а затем произойдет // присваивание). Digit Pref=--Z; // показываем результат работы // префиксной формы cout<<"\nPrefix\n"; cout<<"\nObject Pref:\n"; Pref.display(); cout<<"\nObject Z (after):\n"; Z.display(); cout<<"\n-----------------\n"; // присваиваем объекту Postf выражение // с постфиксной формой (в данном случае // (к сожалению) снова сначала // изменится Z, а затем произойдет // присваивание). Digit Postf=Z--; // показываем результат работы // постфиксной формы cout<<"\nPostfix\n"; cout<<"\nObject Postf:\n"; Postf.display(); cout<<"\nObject Z (after):\n"; Z.display();} ______________________________________________________________ Результат работы программы: Object Z (before): Digit: N = 100 ----------------- Prefix Object Pref: Digit: N = 10 Object Z (after): Digit: N = 10 ----------------- Postfix Object Postf: Digit: N = 1 Object Z (after): Digit: N = 1

В современной же версии языка C++ принято следующее соглашение:

Перегрузка префиксных операций ++ и -- ничем не отличается от перегрузки других унарных операций. Другими словами, функции конкретного класса: operator++ и operator--, определяют префиксные операции для этого класса.

При определении постфиксных операций "++" и "--" операции-функции должны иметь еще один дополнительный параметр типа int. Когда в программе будет использовано постфиксное выражение, то вызывается версия функции с параметром типа int. При этом параметр передавать !не нужно!, а значение его в функции будет равно нулю.

#include <iostream>using namespace std; // Класс, реализующий работу с "парой чисел"class Pair{ // Целое число. int N; // Вещественное число. double x; public: // Конструктор c параметрами Pair(int n, double xn) { N = n; x = xn; } // функция для показа данных на экран void display() { cout << "\nPair: N = " << N << " x = " << x << "\n"; } // Компонентная функция (префиксная --): Pair& operator -- () { // Уменьшаем содержимое объекта // в десять раз и возвращаем его // на место вызова оператора N /= 10; x /= 10; return *this; } // Компонентная функция (постфиксная --): Pair& operator -- (int k) { // временно сохраняем содержимое // объекта в независимую // переменную типа Pair // (Попытка использовать здесь // значение дополнительного параметра // int k подтверждает его равенство 0.) Pair temp(0,0.0); temp.N=N+k; temp.x=x+k; // уменьшаем объект в 10 раз N /= 10; x /= 10; // возвращаем прежнее значение объекта. // таким "тактическим ходом" // мы добиваемся эффекта постфиксной // формы, т. е. в ситуации А=B++ // в А записывается текущее // значение объекта B, тогда как сам B // изменяется return temp; }};void main(){ // создаем объект Z именно с ним // мы и будем экспериментировать Pair Z(10,20.2); // показ объекта в первозданном виде cout<<"\nObject Z (before):\n"; Z.display(); cout<<"\n-----------------\n"; // присваиваем объекту Pref выражение // с префиксной формой (в данном случае // сначала изменится Z, а затем произойдет // присваивание). Pair Pref=--Z; // показываем результат работы // префиксной формы cout<<"\nPrefix\n"; cout<<"\nObject Pref:\n"; Pref.display(); cout<<"\nObject Z (after):\n"; Z.display(); cout<<"\n-----------------\n"; // присваиваем объекту Postf выражение // с постфиксной формой (в данном случае // сначала произойдет присваивание, // а затем изменится Z). Pair Postf=Z--; // показываем результат работы // постфиксной формы cout<<"\nPostfix\n"; cout<<"\nObject Postf:\n"; Postf.display(); cout<<"\nObject Z (after):\n"; Z.display();} ______________________________________________________________ Результат работы программы: Object Z (before): Pair: N = 10 x = 20.2 ----------------- Prefix Object Pref: Pair: N = 1 x = 2.02 Object Z (after): Pair: N = 1 x = 2.02 ----------------- Postfix Object Postf: Pair: N = 1 x = 2.02 Object Z (after): Pair: N = 0 x = 0.202

Примечание:В двух, вышеописанных примерах, мы не используем конструктор копирования, несмотря на то, что здесь присутствует инициализация одного объекта другим при создании. Это связано с тем, что в этом нет необходимости, так как здесь побитовое копирование не несет критического характера. Так что нет смысла перегружать код лишней конструкцией.

Предыдущая Оглавление Следующая
Предыдущая Оглавление Следующая






©2015 arhivinfo.ru Все права принадлежат авторам размещенных материалов.