Перегрузка операторов в С++

Иногда хочется проявить творчество и облегчить программный код  для себя и для других. Для себя написание, для других понимание. Скажем, если в нашей программе часто встречается функция добавления  одной строки в конец другой, конечно, можно это реализовать разными способами. А если мы, в каком-то участке нашего кода, напишем, к примеру так:

char str1[15] = "Hello ";

char str2[] = "world!";

str1 + str2;

и в результате получим строку «Hello world!». Правда, было бы замечательно? Ну так пожалуйста! Сегодня вы научитесь «объяснять» компьютеру,  что оператором  +  вы хотите сложить не два числа, а две строки. И работа со строками — это один из самых удачных, на мой взгляд,  примеров, чтобы начать разбираться с темой «Перегрузка операторов».

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

#include <iostream>
#include <string.h>

using namespace std;

class StringsWork
{
private:
	char str[256];//строка, которая доступна классу
public:
	StringsWork()//конструктор в котором очистим строку класса от мусора
	{
		for(int i = 0; i < 256; i++)  str[i] = '\0';
	}

	void operator +(char*);//прототип метода класса в котором мы перегрузим оператор +
	void getStr();//метод вывода данных на экран
};

void StringsWork::operator +(char *s) //что должен выполнить оператор +
{
	strcat(str, s); //сложение строк
}

void StringsWork::getStr()
{
	cout << str << endl << endl;//вывод символьного массива класса на экран
}

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

	char *str1 = new char [strlen("У лукоморья дуб зелёный;\n")+1]; //выделим память для строк
	char *str2 = new char [strlen("Всё ходит по цепи кругом;\n")+1];
	char *str3 = new char [strlen("И днём и ночью кот учёный\n")+1];
	char *str4 = new char [strlen("Златая цепь на дубе том:\n")+1];

	strcpy(str1,"У лукоморья дуб зелёный;\n");//инициализируем
	strcpy(str2,"Всё ходит по цепи кругом;\n");
	strcpy(str3,"И днём и ночью кот учёный\n");
	strcpy(str4,"Златая цепь на дубе том:\n");

		cout << "1) " << str1;
		cout << "2) " << str2;
		cout << "3) " << str3;
		cout << "4) " << str4 << endl;

	StringsWork story;//создаем объект и добавяем в него строки с помощью перегруженного +
		story + str1;
		story + str4;
		story + str3; 
		story + str2;

		cout << "========================================" << endl;
		cout << "Стих, после правильного сложения строк: " << endl;
		cout << "========================================" << endl << endl;
	story.getStr();

	//Отмечу, что для числовых типов данных оператор плюс будет складывать значения, как и должен
	int a = 5;
	int b = 5;
	int c = 0;

	c = a + b;
	cout << "========================================" << endl << endl;
	cout << "a = " << a << endl  << "b = " << b << endl;
	cout << "c = " << a << " + " << b << " = " << c << endl << endl;

	delete [] str4;//освободим память
	delete [] str3;
	delete [] str2;
	delete [] str1;

	return 0;
}

Разберемся:

Что-то новое в коде мы увидели в строке 16 void operator +(char*);  Тут мы объявили прототип метода класса в котором перегрузим наш оператор +.  Чтобы перегрузить оператор необходимо использовать зарезервированное слово operator. Выглядит это так, словно вы определяете обычную функцию: void operator+ () {//код} В теле этой функции мы размещаем код, который покажет компилятору, какие действия будет выполнять оператор + (или какой-либо другой оператор). Перегруженный оператор будет выполнять указанные  для него действия  только в пределах того класса, в котором он определен. Ниже, в строках 20 — 23 мы уже  определяем какую роль будет играть  + в нашем классе. А именно, с помощью функции   strcat(str, s);  он будет дописывать содержимое строки s , которую мы передали по указателю, в конец строки str.  Строки 17, 25 — 28 это обычный метод класса, с помощью которого строка класса будет показана на экран. Если вам не понятно, как  определять методы класса вне тела класса, т.е. такой момент как void StringsWork::getStr() {//определение}, то вам сначала желательно сходить сюда. Далее, уже  в главной функции main(), в строках 34 — 37,создаем четыре указателя на строки и выделяем необходимое количество памяти для каждой из них, не забывая о том, что для символа '\0' так же надо зарезервировать одну ячейку char *str1 = new char [strlen("текст")+1];. Затем копируем  в них текст с помощью функции strcpy()  и показываем их на экран —  строки 39 — 47. А в строке 49 создаем объект класса. При его создании сработает конструктор класса и строка класса будет очищена от лишних данных. Теперь нам остается только сложить строки в правильной последовательности, используя перегруженный оператор + — строки 50 — 53 и посмотреть, что получилось — строка 58.

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

CppStudio.com

1) У лукоморья дуб зелёный;
2) Всё ходит по цепи кругом;
3) И днём и ночью кот учёный
4) Златая цепь на дубе том:

========================================
Стих, после правильного сложения строк:
========================================

У лукоморья дуб зелёный;
Златая цепь на дубе том:
И днём и ночью кот учёный
Всё ходит по цепи кругом;
========================================

a = 5
b = 5
c = 5 + 5 = 10

Ограничения перегрузки операторов

  • перегрузить можно практически любой оператор, за исключением следующих:

.  точка (выбор элемента класса);  

* звездочка (определение или разыменование указателя);

::  двойное двоеточие (область видимости метода);  

?:  знак вопроса с двоеточием (тернарный оператор сравнения);

#  диез (символ препроцессора);  

##  двойной диез (символ препроцессора);  

sizeof оператор нахождения размера объекта в байтах;     

  • с помощью перегрузки невозможно создавать новые символы для операций;
  • перегрузка операторов не изменяет порядок выполнения операций и их приоритет;
  • унарный оператор не может использоваться для переопределения бинарной операции так же, как и бинарный оператор не переопределит унарную операцию.

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

Нельзя не отметить, что многие программисты негативно относятся к перегрузке операторов. Сама возможность перегрузки операторов предоставлена для  облегчения понимания и читаемости кода программ. В то же время, она наоборот может стать и причиной усложнения вашей программы и многим программистам будет тяжело ее понять. Помните о «золотой середине» и используйте перегрузку только тогда, когда она реально принесет пользу вам и другим.  Вполне можно обойтись и без перегрузки операторов. Но это не значит, что можно проигнорировать данную тему. В ней следует разобраться хотя бы потому, что вам когда-то придется столкнуться с перегрузкой в чужом коде и вы сможете легко разобраться что к чему.

Вот мы очень коротко ознакомились с перегрузкой операторов в С++. Увидели, так сказать, вершину айсберга. А вашим домашним заданием (ДА-ДА — ДОМАШНИМ ЗАДАНИЕМ!) будет доработать программу, добавив в нее перегрузку оператора для удаления строки. Какой оператор перегружать выберите сами. Либо предложите свой вариант апгрейда кода, добавив в него то, что посчитаете нужным и интересным.  Ваши «труды» можете добавлять в комментарии к этой статье. Нам интересно будет посмотреть ваши варианты решения. Удачи!

Практика

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

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

Комментарии

  1. Stanisław Pietkiewicz

    АААА…. Как написать символ конца строки?

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

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