Перегрузка операторов в С++ (часть 2)

Эта статья является дополнением к статье «Перегрузка операторов в С++». В ней будет рассмотрена перегрузка операций  =  (присваивание), == (равенство) и [ ] (индексация).  Думаю, новичкам будет полезно попрактиковаться и увидеть некоторые нюансы их перегрузки.

Поставим перед собой следующие задачи:

  • создать класс, который будет содержать элементы:  int *numbers — указатель на массив целых чисел  и sizeOfArray — размер этого массива;
  • перегрузить оператор [] так, чтобы мы могли из main-функции присваивать значение элементам массива класса.  Например, написав выражение Object[0] = 3, значение 3 запишется в ячейку с индексом 0 массива int *numbers. Теперь нам не придется определять и вызывать метод, который бы выполнял эту операцию (к примеру: Object.setNumber(0,3); где 0 – индекс массива а 3 – то что нужно записать);
  • перегрузить оператор   ==  чтобы можно было сравнить массивы  int *numbers  двух разных объектов класса;
  • перегрузить оператор  =  так, чтобы записав выражение Object = Object2 массив int *numbers объекта Object  стал идентичными массиву объекта  Object2 и по количеству ячеек массива и по значениям, которые хранят ячейки массива.

 Вот решение:

#include <iostream>
using namespace std;

class MyArray
{
	int *numbers;
	int sizeOfArray;
public:
	MyArray()		//конструктор без параметров
	{
		sizeOfArray = 0;	
		numbers = 0;
	}
//-----------------------------------------------
	MyArray(int size)		//конструктор с параметрами
	{
		sizeOfArray = size;	
		numbers = new int [sizeOfArray];
		for(int i = 0; i < sizeOfArray; i++)
		{
			numbers[i] = 0;
		}
	}
//-----------------------------------------------
	~MyArray()		//деструктор
	{
		delete [] numbers;
	}
//-----------------------------------------------
	void showData()			//вывод данных массива на экран
	{
		for(int i = 0; i < sizeOfArray; i++)
		{
			cout << numbers[i] << " | ";
		}
	cout << endl << endl;
	}
//-----------------------------------------------
	// на место вызова [] вернется по ссылке сам объект 
	int &operator[](int j) //перегрузка []		
	{
		return numbers[j];
	}
//-----------------------------------------------

	MyArray& operator=( MyArray &arrInt2 ) //перегрузка оператора присваивания
	{
		delete [] numbers;

		sizeOfArray = arrInt2.sizeOfArray;

		numbers = new int [sizeOfArray];
		for (int i = 0; i < sizeOfArray; i++)
		{
			numbers[i] = arrInt2.numbers[i];
		}

		return *this;
	}
//-----------------------------------------------
	friend bool operator ==( MyArray &arrInt, MyArray &arrInt2 ); //перегрузка ==
};

bool operator == ( MyArray &arrInt, MyArray &arrInt2 ) 
{
	if(arrInt.sizeOfArray != arrInt2.sizeOfArray) //сравниваем размеры массивов объектов
	{
		cout << "В массивах разное количество элементов\n";
		return 0;
	}
	else //проверяем равны ли данныев в ячейках массивов
	{		
		for (int i = 0; i < arrInt.sizeOfArray; i++)
		{
			if(arrInt.numbers[i] != arrInt2.numbers[i])
			{
				cout << "Значения массивов не равны\n";
				return 0;
			}				
		}	
	}
return 1; 
}

int main()
{
	setlocale(LC_ALL, "rus");

	MyArray ArrayInt(5);	//создаем объект класса и записываем в него данные
	ArrayInt[0] = 1; //перегруженный []
	ArrayInt[1] = 2;
	ArrayInt[2] = 3;
	ArrayInt[3] = 4;
	ArrayInt[4] = 5;
	cout << "Массив ArrayInt:  ";
	ArrayInt.showData();	//вывод данных массива на экран

	MyArray ArrayInt2(5); //создаем второй объект класса
	ArrayInt2[0] = 11; //перегруженный []
	ArrayInt2[1] = 22;
	ArrayInt2[2] = 33;
	ArrayInt2[3] = 44;
	ArrayInt2[4] = 55;
	cout << "Массив ArrayInt2: ";
	ArrayInt2.showData();	//вывод данных массива на экран

	if(ArrayInt == ArrayInt2){ //сравнение двух объектов класса (перегруженный ==)
		cout << "Массив ArrayInt равен массиву ArrayInt2\n";
	}
	else {
		ArrayInt = ArrayInt2;
	}
	cout << "Массив ArrayInt после копирования:  ";
	ArrayInt.showData();

	MyArray ArrayInt3(10); // третий объект класса с массивом из 10 элементов 
	cout << "Массив ArrayInt3: ";
	ArrayInt3.showData();
	ArrayInt3 = ArrayInt; // копируем массив из ArrayInt в ArrayInt3
	cout << "Массив ArrayInt3 после копирования: \n";
	ArrayInt3.showData();

	return 0;
}

И так — определяем класс MyArray .  В строках 9 — 28 определены конструкторы и деструктор.  Тот конструктор, который принимает параметр, будет сразу, при создании объекта класса, задавать размер sizeOfArray массива numbers. В строках 39-43 перегружаем оператор индексирования []. На место вызова [] вернется по ссылке сам объект и в ячейку его массива numbers  под номером j мы сможем записать целое число.    

Ниже в строках 46 — 59 перегружаем = (присваивание). Он будет копировать массив одного объекта класса MyArray в массив другого объекта класса. Чтобы это произошло, достаточно будет написать следующее выражение Object = Object2. При использовании перегруженного =, вызывается функция  MyArray& operator=( MyArray &arrInt2 ) определенная в классе.  Первый параметр (объект класса который прописан слева от знака = ) в нее передается неявным образом по указателю this, а тот, что в скобках – это тот объект который указан справа от =. Далее выполняется код тела этой функции – определение нового размера массива первого объекта и корректное копирование в него данных элементов массива второго объекта. Возвращает функция указатель на объект return *this; (указатель на самого себя, только уже с внесенными изменениями).

Перегрузка == (равенства) у нас определена в строках 64 — 83. А в теле класса прописан ее прототип, как дружественной функции класса. Так как оператор == используется для сравнения объектов, то функция его перегрузки  будет возвращать значение типа bool.  Она вернет 1, если массивы объектов равны  и по размеру и, по значениям в ячейках массивов. А если нет – вернет 0 и соответствующее сообщение о том,  что не совпадает.

Ну а в  main() мы просто применяем все перегруженные операторы так, как нам надо для работы.

Результат работы программы:

CppStudio.com

Массив ArrayInt: 1 | 2 | 3 | 4 | 5 |

Массив ArrayInt2: 11 | 22 | 33 | 44 | 55 |

Значения массивов не равны
Массив ArrayInt после копирования: 11 | 22 | 33 | 44 | 55 |

Массив ArrayInt3: 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |

Массив ArrayInt3 после копирования:
11 | 22 | 33 | 44 | 55 |

Практика

К сожалению, для данной темы пока нет подходящих задач. Если у вас есть таковые на примете, отправте их по адресу: admin@cppstudio.com. Мы их опубликуем!

Автор: Marienko L.
Дата: 23.04.2014
Поделиться:

Комментарии

  1. Данил Токарев

    Да уж. Шел по порядку и застопорился на этой статье -.- Вот нафига нужны эти ‘&‘? Почему перегруженный оператор должен вернуть именно ссылку? (я про «[ ]» и «=«)

  2. npavelFax

    Работа через интернет официальное трудоустройство.

  3. Georgy Petrov

    #include "stdafx.h"
    #include <iostream>
    #include <ctime>
    
    using namespace std;
    
    class C_overload{
    	int *ar;
    	int SZ;
    public:
    	C_overload(int n){ SZ = n; ar = new int[SZ]; }
    	//~C_overload(){ delete [] ar; }
    	void get(){
    		//srand(time(0));
    		for (int i = 0; i < SZ; i++){
    			ar[i] = rand() % 10;
    		}
    	}
    	void show(){
    		for (int i = 0; i < SZ; i++){
    			cout << ar[i]<<' ';
    		}
    		cout << endl;
    	}
    	int& operator[](int i){ return ar[i]; }
    	bool operator==(C_overload a_){
    		int rez;
    		while (true){
    			if ((rez = *ar - *a_.ar++) != 0 || !*ar++) break;
    		}
    		if (!rez) return 1;
    		else return 0;
    	}
    	C_overload operator=(C_overload &_a){
    		delete ar;
    		ar = new int[_a.SZ+1];
    		SZ = _a.SZ;
    
    		for (int i = 0; i < SZ; i++){
    			ar[i] = _a.ar[i];
    		}
    		return *this;
    	}
    };
    int _tmain(int argc, _TCHAR* argv[])
    {
    	C_overload array(3);
    	array.get();
    	cout << "ar1= ";
    	array.show();
    	array[1] = 0;
    	cout << "ar1= ";
    	array.show();
    
    	C_overload array2(3);
    	array2[0] = 2;
    	array2[1] = 0;
    	array2[2] = 4;
    	cout << "ar2= ";
    	array2.show();
    
    	if (array == array2){ cout << "Eq"; }
    	else { array = array2; cout << "not yet" << endl; }
    
    	cout << "ar1= ";
    	array.show();
    
    
    	_gettch();
    	return 0;
    }
    Проблема 1) Деструктор ругается на временные объекты в моих методах (когда метод заканчивается по идее он удаляет их), & ссылка не помогла, функцию сравнения переделал из библиотечной cmpstr()
    2) frined если написать, то тоже ругается
  4. JIeo

    Программа поломается если причсвоить самого себя…Тут ляп такчто думайте лучше…где эта ошибка и как ее поличить…

  5. JIeo

    Странно тут ляп большой ,если попробывыть присвоить самого себя то все паломается…
    В операторе присваивания

    if(this!=& arrInt2){

    все что написано там…

    }

     

Оставить комментарий

Вы должны войти, чтобы оставить комментарий.