Главная » Статьи » Програмування » C++ [ Добавить статью ]

RUS Уроки по программированию на языке С++ (Перегрузка инкремента и декремента.)

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

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

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

Категория: C++ | Добавил: DEN-SHP (06.11.2012)
Просмотров: 1680 | Рейтинг: 5.0/1
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]