Эта статья является дополнением к статье «Перегрузка операторов в С++». В ней будет рассмотрена перегрузка операций = (присваивание), == (равенство) и [ ] (индексация). Думаю, новичкам будет полезно попрактиковаться и увидеть некоторые нюансы их перегрузки.
Поставим перед собой следующие задачи:
- создать класс, который будет содержать элементы:
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() мы просто применяем все перегруженные операторы так, как нам надо для работы.
Результат работы программы:
Массив 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 |
Комментарии
Данил Токарев
Да уж. Шел по порядку и застопорился на этой статье -.- Вот нафига нужны эти ‘&‘? Почему перегруженный оператор должен вернуть именно ссылку? (я про «[ ]» и «=«)
npavelFax
Работа через интернет официальное трудоустройство.
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 если написать, то тоже ругаетсяJIeo
Программа поломается если причсвоить самого себя…Тут ляп такчто думайте лучше…где эта ошибка и как ее поличить…
JIeo
Странно тут ляп большой ,если попробывыть присвоить самого себя то все паломается…
В операторе присваивания
if(this!=& arrInt2){
все что написано там…
}