Перегрузка постфиксных операторов



 

До сих пор рассматривалась перегрузка оператора преинкремента. Что если перегрузить оператор постинкремента? Тут перед компилятором встает проблема: как различить между собой операторы постинкремента и преинкремента. Существует договоренность, что при определении функции оператора постинкремента устанавливается целочисленный параметр. Значение параметра не имеет смысла. Он используется только как флаг, который сообщает, что перед нами оператор постинкремента.

 

Различия между преинкрементном и постинкрементном

 

Прежде чем приступить к перегрузке оператора постинкремента, следует четко понять, чем он отличается от оператора преинкремента. Подробно эта тема рассматривалась на занятии 4 (см. листинг 4.3).

Вспомните, преинкремент означает прирастить, затем возвратить значение, а постинкремент — возвратить значение, а потом прирастить.

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

Давайте все это повторим еще раз. Посмотрите на следующее выражение:

а = x++;

Если исходно переменная x равнялась 5, то в этом выражении переменной а будет присвоено значение 5, зато переменная x станет равной 6. Если x не просто переменная, а объект, то его оператор постинкремента должен сохранить исходное значение 5

во временном объекте, прирастить значение объекта x до 6, после чего возвратить значение временного объекта и присвоить его объекту а.

Обратите внимание, что, поскольку речь идет о временном объекте, его следует возвращать как значение, а не как ссылку, так как временный объект выйдет из области видимости как только функция возвратит свое значение. В листинге 10.12 показано использование обоих операторов.

Листинг 10.12. Операторы преинкремента и постинкремента

1: // Листинг 10.12.

2: // Возвращение разыменованного указателя this

3:

4: int

5: #include <iostream.h>

6:

7: class Counter

8: {

9: public:

10: Counter();

11: ~Counter(){ }

12: int GetItsVal()const { return itsVal; }

13: void SetItsVal(int x) { itsVal = x; }

14: const Counter& operator++ (); // оператор преинкремента

15: const Counter operator++ (int); // оператор постинкремента

16:

17: private:

18: int itsVal;

19: };

20:

21: Counter::Counter():

22: itsVal(0)

23: { }

24:

25: const Counter& Counter::operator++()

26: {

27: ++itsVal;

28: return *this;

29: }

30:

31: const Counter Counter::operator++(int x)

32: {

33: Counter temp(*this);

34: ++itsVal;

35: return temp;

36: }

37:

38: int main()

39: {

40: Counter i;

41: cout << "The value of i is " << i.GetItsVal() << endl;

42: i++;

43: cout << "The value of i is " << i.GetItsVal() << endl;

44: ++i;

45: cout << "The value of i is " << i.GetItsVal() << endl;

46: Counter а = ++i;

47: cout << "The value of а: " << a.GetItsVal();

48: cout << " and i: " << i.GetItsVal() << endl;

49: а = i++;

50: cout << "The value of а: " << a.GetItsVal();

51: cout << " and i: " << i.GetItsVal() << endl;

52: return 0;

53: }

 

Результат:

The value of i is 0

The value of i is 1

The value of i is 2

The value of a: 3 and i: 3

The value of a: 3 and i: 4

 

Анализ: Оператор постинкремента объявляется в строке 15 и выполняется в строках с 31 по 36. Обратите внимание, что в объявлении оператора преинкремента в строке 14 не задан целочисленный параметр x, выполняющий роль флага. При определении оператора постинкремента используется флагх, чтобы указать компилятору, что это именно постинкремент. Значение параметра x нигде и никогда не используется.

 

Синтаксис перегрузки операторов с одним операндом

Объявление перегруженных операторов выполняется так же, как и функций. Используйте ключевое слово operator, за которым следует сам перегружаемый оператор. В функциях операторов с одним операндом параметры не задаются, за исключением операторов no- стинкремента и постдекремента, в которых целочисленный параметр играет роль флага. Пример перегрузки оператора преинкремента:

const Counter&Countcr::operator++ ();

Пример перегрузки оператора постдекремента:

const Counter&Counter::operator-- (int);

 

Оператор суммирования

 

Операторы приращения, рассмотренные выше, оперируют только с одним операндом. Оператор суммирования (+) — это представитель операторов с двумя операндами. Он выполняет операции с двумя объектами. Как выполнить перегрузку оператора суммирования для класса Counter?

Цель состоит в том, чтобы объявить две переменные класса Counter, после чего сложить их, как в следующем примере:

Counter переменная_один, переменная_два, переменная_три; переменная_три= переменная_один + переменная_два;

Начнем работу с записи функции Add(), в которой объект Counter будет выступать аргументом. Эта функция должна сложить два значения, после чего возвратить Counter с полученным результатом. Данный подход показан в листинге 10.13.

Листинг 10.13. Функция Add()

1: // Листинг 10.13.

2: // Функция Add

3:

4: int

5: #include <iostream.h>

6:

7: class Counter

8: {

9: public:

10: Counter();

11: Counter(int initialValue);

12: ~Counter(){ }

13: int GetItsVal()const {return itsVal; }

14: void SetItsVal(int x) {itsVal = x; }

15: Counter Add(const Counter &);

16:

17: private:

18: int itsVal;

19:

20: };

21:

22: Counter::Counter(int initialValue):

23: itsVal(initialValue)

24: { }

25:

26: Counter::Counter();

27: itsVal(0)

28: { }

29:

30: Counter Counter::Add(const Counter & rhs)

31: {

32: return Counter(itsVal+ rhs.GetItsVal());

33: }

34:

35: int main()

36: {

37: Counter varOne(2), varTwo(4), varThree;

38: varThree = varOne.Add(varTwo);

39: cout << "var0ne: " << varOne.GetItsVal()<< endl;

40: cout << "varTwo: " << varTwo.GetItsVal() << endl;

41: cout << "varThree: " << varThree.GetItsVal() << endl;

42:

43: return 0;

44: }

 

Результат:

varOne: 2

varTwo: 4

varThree: 6

 

Анализ: Функция Add() объявляется в строке 15. В функции задана константная ссылка на Counter, представляющая число, которое нужно добавить к текущему объекту. Функция возвращает объект класса Counter, представляющий собой результат суммирования, который присваивается операнду слева от оператора присваивания (=), как показано в строке 38. Здесь переменная varOne является объектом, varTwo — параметр функции Add(), а varThree — адресный операнд, которому присваивается результат суммирования.

Чтобы создать объект varThree без исходной инициализации каким-либо значением, используется конструктор, заданный по умолчанию. Он присваивает объекту varThree нулевое значение, как показано в строках 22—24. Иначе эту проблему можно было решить, присвоив нулевое значение конструктору, определенному в строке 11.

 


Дата добавления: 2019-02-12; просмотров: 250; Мы поможем в написании вашей работы!

Поделиться с друзьями:






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