Программирование на C и C++

Онлайн справочник программиста на C и C++

Применение перезагрузки операторов

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

Для начала объявим следующий класс str_type:

#include <iostream.h>
#include <string.h>
class str_type {
char string[80];
public:
str_type(char *str = "\0") { strcpy(string, str); }
str_type operator+(str_type str); // конкатенация
str_type operator=(str_type str); // присвоение
// вывод строки
void show_str() { cout << string; }
};

В этом типе содержатся объявления частного массива из 80 символов. Для простоты будем рас­сматривать только строки, содержащие не более 79 байт. У класса имеется конструктор, с помо­щью которого можно инициализировать массив string заданными значениями или присвоить ну­левую строку в случае отсутствия инициализации. Также объявляются два перегруженных оператора, выполняющих конкатенацию (то есть сложение строк) и присвоение. Наконец, объяв­ляется функция show_str(), выводящая строку на экран. Ниже показаны перегружаемые функции-операторы:

// конкатенация двух строк
str_type str_type::operator+(str_type str) {
str_type temp;
strcpy(temp.string, string);
strcat(temp.string, str.string);
return temp;
}
// присвоение одной строки другой
str_type str_type::operator=(str_type str) {
strcpy(string, str.string);
return *this;
}

Использование данных определений иллюстрируется в функции main():

int main()
{
str_type a ("Hello "), b( "There"), c;
с = a + b;
с.show_str();
return 0;
}

Эта программа выводит текст: «Hello There». Сначала осуществляется конкатенация а и b, а затем результат присваивается с.

Надо иметь в виду, что оба оператора = и + определены только для объектов типа str_type. Например, следующая инструкция неверна

а = "this is currently wrong";

потому что в ней происходит попытка присвоить объекту а обычную строку. Однако можно усовер­шенствовать класс str_type, чтобы позволять выполнять такие инструкции. Для этого необходимо пе­регрузить операторы + и = еще раз. Для начала изменим объявление класса, как показано ниже:

class str_type {
char string[80];
public:
str_type(char *str = "\0") { strcpy(string, str); }
str_type operator+ (str_type str); // конкатенация объектов
str_type operator+(char *str); /* конкатенация объекта со строкой */
str_type operator=(str_type str); /* присвоение объекта объекту */
char *operator=(char *str); // присвоение строки объекту
void show_str() { cout << string; }
};

Перегруженные operator+() и operator=() реализованы ниже:

// присвоение строки объекту
str_type str_type::operator=(char *str)
{
str_type temp;
strcpy(string, str);
strcpy(temp.string, string);
return temp;
}
// добавление строки к объекту
str_type str_type::operator+(char *str)
{
str_type temp;
strcpy(temp.string, string);
strcat (temp.string, str);
return temp;
}

Посмотрим внимательно на эти функции. Обратим внимание, что правый аргумент не является объектом типа str_type, а служит указателем на массив символов — то есть на обычную строку языка С++.
Кроме того, обратим внимание, что обе функции возвращают объекты типа str_type. Хотя функции в теории могут возвращать любые другие типы, имеет смысл возвращать объект, поскольку эти опера­торы применяются также к объектам. Временно, чтобы наши инструкции выглядели естественным образом, мы и определили строковые операторы, которые могут принимать обычные строки С++ в качестве правых операндов. Теперь следующие инструкции являются законными:

str_type а, b, с;
а = "hi there"; // присвоение объекту строки
с = а + " George"; // конкатенация объекта со строкой

Следующая программа включает в себя дополнительные значения для операторов + и = и ил­люстрирует их использование:

/ / расширение строкового типа
#include <iostream.h>
#include <string.h>
class str_type {
char string[80];
public:
str_type(char *str = "\0") { strcpy(string, str); }
str_type operator+(str_type str);
str_type operator+(char *str);
str_type operator= (str_type str);
str_type operator=(char *str);
void show_str() { cout  << string; }
};
str_type str_type::operator+(str_type str) {
str_type temp;
strcpy(temp.string, string);
strcat(temp.string, str.string);
return temp;
}
str_type str_type::operator= (str_type str) {
strcpy(string, str.string);
return *this;
}
str_type str_type::operator=(char *str)
{
str_type temp;
strcpy(string, str);
strcpy(temp.string, string);
return temp;
}
str_type str_type::operator+ (char *str)
{
str_type temp;
strcpy(temp.string, string);
strcat (temp.string, str);
return temp;
}
int main()
{
str_type a("Hello "), b("There"), c;
с = a + b;
с.show_str();
cout << "\ n ";
a = "to program in because";
a.show_str();
cout << "\ n ";
b = с = "С++ is fun";
с = c+" "+a+" "+b;
с.show_str();
return 0;
}

Эта программа выводит на экран следующий текст:

Hello There to program in because
С++ is fun to program in because С++ is fun

Теперь можно попробовать создать свои строковые операторы самостоятельно. Например, мож­но определить операцию «минус» таким образом, чтобы она выполняла уничтожение части строки. Например, если объект А строкового типа содержит текст «This is a test», а объект В содержит «is», то А—В соответствует «th a test». В данном случае все вхождения подстроки удаляются из исходной строки.