1 2 3 4 |
String S1 = "лето"; String S2 = "хорошее"; S1 + " " + << S2; //на выходе "лето хорошее" |
a += b //--- короткая форма --- // a = a + b; //--- полная форма -- //
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
//Листинг #1 Перегрузка += для самописного класса string clang #include <iostream> #include <cstring> using namespace std; class String{ public: String(const char*); const char* operator+(const char* rvalue); // <--- Прототип конструктора класса с параметром, будет принят указатель на константную строку void operator+=(const char* rvale); // <--- Прототип функция-члена класса. Функция будет учить класс использовать += void print() { cout << data; } // <--- Функция-член класса, она используется для вывода на экран строки, // которая хранится внутри объекта класса private: char data[256]; // <--- Строка, которую хранит объект класса }; String::String(const char* str){ //Конструктор класса описан вне класса. strcpy(data, str); //Копируем пришедший параметр в строку класса. } void String::operator+=(const char* rvalue){ //Функция-член класса описана вне класса strcat(data, rvalue); //Используем, как используем обычные функции. //Объединяем строку класса (data) со строкой, которая указана //справа от оператора += } int main(){ String MyStr = "String One"; //Создаём первый объект MyStr+=" String two"; //Складываем две строки MyStr.print(); //Выводим результат на экран } |
В качестве параметра, в круглых скобках, указывается такой объект, тип которого соответствует типу объекта, стоящего справа от объекта, к которому операция применяется. Всё остальное — это то же самое, что и обычные функции. Важно только отметить, что для перегрузки операций всегда используется ключевое слово operator, оно даёт знать компилятору, что это операция, а не функция.
1 2 |
String MyStr = "String One", MyStr2 = "Two string"; MyStr += MyStr2; //Не сработает. Класс не научен такому действию |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
//Литинг #2 Перегрузка самописного класса "string" clang #include <iostream> #include <cstring> using namespace std; class String{ public: String(const char*); const char* operator+(const char* rvalue); void operator+=(const char* rvale); void operator+=(String &rvalue); void print() { cout << data; } const char* get_data() { return data; } private: char data[256]; }; String::String(const char* str){ strcpy(data, str); } void String::operator+=(const char* rvalue){ //Перегрузка оператора += strcat(data, rvalue); } void String::operator+=(String &rvalue){ //Перегрузка оператора += strcat(data, rvalue.get_data()); } int main(){ String MyStr = "String One", MyStr2 = "Two string"; MyStr += MyStr2; //Складываем объект с таким же объектом как он сам MyStr.print(); MyStr += "1111"; //Складываем объект с константной строкой MyStr.print(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
//Листинг #3 Перегрузка операций clang #include <iostream> #include <cstring> #include <string.h> using namespace std; class String{ public: String(const char*); //Прототип конструктора класса, принимающего параметр void operator+=(const char* rvalue); //Прототип перегрузки бинарного += void operator+=( String &rvalue); //Прототип перегрузки бинарного += void operator-(String &rvalue); //Прототип перегрузки бинарного минуса void print() { cout << data << '\n'; } //Функция вывода на экран значения переменной data const char* get_data() { return data; } //Функция-геттер, получает значение переменной data private: char data[256]; }; String::String(const char* str){ //Конструктор класса с параметром strcpy(data, str); } void String::operator+=( String &rvalue){ //Перегрузка += strcat(data,rvalue.get_data()); } void String::operator+=(const char* rvalue){ //Перегрузка += strcat(data,rvalue); } void String::operator-(String &rvalue){ int X = strstr(data,rvalue.get_data()) - data; //Поиск позиции, где начинается строка if (X>=0) { strcpy(data+X,data+X+strlen(rvalue.get_data())); } //Обрезание строки } int main(){ String MyStr = "String One", MyStr2 = "Two string"; MyStr+=" "; //Складываем объект нашего типа с объектом типа "константная строка" MyStr.print(); //Выводим на экран. MyStr+=MyStr2; //Складываем объект нашего типв с объектом нашего типа MyStr.print(); //Выводим на экран MyStr+="12345"; MyStr.print(); MyStr-MyStr2; //Вычитаем из объекта нашего типа объект нашего типа MyStr.print(); //Выводим на экран } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
//Листинг #4 Перегрузка + clang #include <iostream> using std::cout; class MyClass{ int x; public: MyClass(const int value):x(value){} //Конструктор класса. Принимает параметр value и //сохраняет value в x void print() const { cout << x; } //Функция-член класса, выводит x на экран. int get_x() const { return x; } //Функция-член класса, просто отдаёт x void operator+(const MyClass& obj){ // Внимание на void x = (*this).get_x() + obj.get_x(); //Складываем значения } }; int main(){ MyClass A = 100, B = 200, C = 0; //Записываем в x значения, соответственно A+B; //Так можно, но делать это много раз немного странно, слегка невыгодно // C = A+B; //из-за возвращаемого void в функции-перегрузке оператора так нельзя A.print(); cout << '\n'; B.print(); cout << '\n'; C.print(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
//Листинг #5.1 Перегрузка операций Нельзя перегружать return clang #include <iostream> using std::cout; class MyClass{ int x; public: MyClass(const int value):x(value){} //Конструктор класса. Принимает параметр value и //сохраняет value в x void print() const { cout << x; } //Функция-член класса, выводит x на экран. int get_x() const { return x; } //Функция-член класса, просто отдаёт x /* Если раскоментировать, то получится перегрузка возвращаемого типа это по стандарту языка сделать нельзя void operator+(const MyClass& obj){ // Внимание на void x = (*this).get_x() + obj.get_x(); } */ int operator+(const MyClass& obj){ // Возвращаем int return (*this).get_x() + obj.get_x(); } }; int main(){ MyClass A = 100, B = 200, C = 0; //Записываем в x значения, соответственно A+B; //Так можно // C = A+B; //из-за возвращаемого void в функции-перегрузке оператора так нельзя A.print(); cout << '\n'; B.print(); cout << '\n'; C.print(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
//Листинг #5.2 Перегрузка операций clang #include <iostream> using std::cout; class MyClass{ int x; public: MyClass(){} //Простой конструктор MyClass(const int value):x(value){} //Конструктор класса. Принимает параметр value и //сохраняет value в x void print(const char* str) const { cout << str << x; } //Функция-член класса, выводит x на экран. int get_x() const { return x; } //Функция-член класса, просто отдаёт x MyClass operator+(const MyClass& obj){ // Возвращаем тип, который соответствует типу объектов нашего класса MyClass TempClass; TempClass.x = (*this).get_x() + obj.get_x(); return TempClass; } }; int main(){ MyClass A = 100, B = 200, C = 0; //Записываем в x значения, соответственно A+B; //Так можно C = A+B; //Так теперь тоже можно A.print( "A.x = "); cout << '\n'; B.print("B.x = "); cout << '\n'; C.print("C.x = "); } |
С большим трудом удалось скомпелировать в Code::Block,но так и не понял что происходит.У меня просто копируется введенная строка и удаляется символ.А как складываются строки так и не увидел..С этой строкой
вылетают ошибки,заменяю на
ошибок нет,но мне кажется и не работает.Пожалуйста объясните в чем дело.Название класса пришлось поменять из за конфликта с инклудой string,и переменные несколько изменить
Пример неправильно описан. Поэтому буду переделывать, но это в течении след. недели. Сейчас нет возможности.
а про конфликты) не юзайте using namespace std и будет меньше геморроя) пишите прямо std::cout,std::string и т.п.
Точнее с минусом неправильно. С плюсом работает.
Например вы вводите 2 слова:
Привет
Пока
Сначала происходит сложение этих двух строк = «Привет Пока»
Потом должен удалиться символ «в», что там получится должно не помню. В общем это зависит от того, что у минуса в классе описано. Можно 1 символ удалять, можно все, можно каждый второй и т.п.
Чтоб другие не мучались код для CodeBlock
Вот так у меня работает правильно.С тегами не получается в виде текста покажу код.
#include
#include
#include
using namespace std;
//СОЗДАЕМ СОБСТВЕННЫЙ КЛАСС
class stroka
{
public:
stroka (char*); //конструктор класса принимающий один параметр
void operator+(char*); //определение оператора +
void operator-(char); //определение оператора —
void show_stroka(void); //метод класса для отображения строки
private:
char data[256]; //символьный массив, доступный только классу
};
stroka::stroka(char *str) //Транзитом через конструктор
{
strcpy(data, str); //копируем в символьный массив класса данные из принимаемой извне строки
}
void stroka::operator+(char *str) //Определяем оператор +
{
strcat(data, str); //как функцию сложения двух строк
}
void stroka::operator-(char letter)//Определяем оператор —
{
char temp[256]; // будем создавать новую строку
int i, j; //счетчики циклов
//Проходим по всей строке класса с помощью цикла и если символ строки не равен принятому символу (параметру), то копируем его в новую строку
for (i = 0, j = 0; data[i]; ++i) if (data[i] != letter) temp[j++] = data[i];
temp[j] = NULL;
strcpy(data, temp); //Копируем новую строку в символьный массив класса
}
void stroka::show_stroka(void)
{
cout << data << endl; //Показываем символьный массив класса
}
int main()
{
char st[256], st2[256]; //Объявление двух указателей для строк
cin.get(st, 256); //Считывание первой строки с клавиатуры
cin.get();
cin.get(st2, 256); //Считывание второй строки с клавиатуры
stroka title(st); //Объявление переменной типа нашего класса и передача в конструктор первой строки
title + " "; //С помощью перегрузки операторов добавили к строке пробел
title + st2; //C помощью перегрузки операторов добавили к строке вторую строку
title.show_stroka(); //Отобразили результирующую строку на экране
title — 'b'; //При помощи перегрузки операторов пытаемся удалить символ в
title.show_stroka(); //Отобразили результирующую строку
return 0;
}
только в этой строке предупреждение старое преобразование title + " "; //С помощью перегрузки операторов добавили к строке пробел
Разобрался и с этим.Переписал так void operator+(char const*); //определение оператора + и void stroka::operator+(char const* str) //Определяем оператор +j.Теперь кампиляция чистая и все работает.
Наверное правильней будет не temp[j] = NULL; а temp[j] = »;
Да. NULL использовать не рекомендуется.
temp ]j] = »;
не получается в ‘ ‘
\ 0
в
private:
char data[256];
я думаю, что очень хорошо
Можно все сделать гораздо проще)
Ну когда уже научатся люди задействовать свой мозг! Ctrl+c,v уже задолбало!
Не ужели этот пример может чему то научить?! Особенно начинающего!
fn.cpp
CFLAGS=-std=gnu++11
all: fn.cpp
g++ $(CFLAGS) -o fn fn.cpp
Пример немного неправильно написан. Вот так лучше:
А вообще, спасибо за участие. Хороший пример.
Нет, не забыл это осталось от предыдущего кода. operator-вообще не обязан что либо возвращать, это тоже известное заблуждение из копипастов. Проверьте, вот так тоже будет работать.
#include "cstring"
#include "cstdio"
class MyStr
{
public:
char str[256];
void operator=(char *pstr)
{
strcpy(str,pstr);
}
};
int main()
{
MyStr a;
a="This is string";
puts(a.str);
return 0;
}
Сейчас уже очень мало людей которые пишут на чистом Си и даже С++. Немодно :). Сейчас принято плодить говнокод на различных фрэймворках и явах. И аргумент — это скорость программирования. Может быть это и так, а вот качество кода при этом ужасно страдает. Быстрых и не требовательных приложений очень мало. И то что существуют такие порталы как ваш — это очень хорошо. Но не отпугивайте начинающих примерами монстрами в которых и опытный прогер не сразу разберется. Удачи, надеюсь что популяция сишников восстановится :)))!
Если указан тип данных не void, обязан.
Это не заблуждение, это факт.
Статья переписана.