Раздел «Язык Си».ClassOperator:

Классы в С++

"Перегрузка операторов."

Числа

Задача про покупки

У человека утром в понедельник были деньги Rub рублей и kop копеек.

По утрам он заходил в кафе, выпивал N чашек чаю и съедал K бутербродов. Чай стоил chr рублей и ckop копеек, а бутерброд - br рублей и bkop копеек. Человек заходил в кафе каждый день кроме воскресенья.

В воскресенье он получил деньги giftr рублей и giftkop копеек. После этого человек решил вычислить сколько у него всего денег.

Написать программу, которая вычисляет количество денег в воскресенье вечером.

Решение

Если бы все цены били бы только в рублях, вычислить деньги было бы очень легко. Достаточно написать формулу:

Sum = Rub - (chr + br) * 6 + giftr

Но есть еще и копейки. Мы уже умеем программировать класс Money, в котором есть и рубли, и копейки: Для таких объектов сложение, вычитание и деление не работает. приходится определять фуннкции: add(), minus(), mult().

// Начало мантры
#include <iostream>
#include <cstdlib>
using namespace std;
// Конец мантры

class Rus{

  int R; // рубли
  int kop; // копейки
 public:
   Rus();
// функция получает деньги с клавиатуры
  void getMoney();
// Функция складывает деньги
  Rus add(Rus money);
// Функция считает сколько осталось после траты money
  Rus minus(Rus money);
// Умножение денег на число (много одинаковых вещей)
  Rus multy(int n);
// печать
  void print();

};
// Здесь нужен код для функций
int main(){

// Здесь решение
}

Если написать код для всех этих функций, то решение будет таким:

int main(){
// Эти деньги были вначале
   Rus startMoney;
// Цена чая
   Rus chay;
// Цена бутерброда
   Rus buterbroad;
// Деньги, которые получил в воскресенье
   Rus gift;
// Деньги, которые будут в воскресенье вечером:
   Rus mymoney;
// Введем значения всех объектов:
   startMoney.getMoney();
   chay.getMoney();
   buterbroad.getMoney();
   gift.getMoney();
//Умножение цены на 6 (чай пили 6 раз)  
  chay = chay.mult(6);
// Бутерброд на 6
  buterbroad = buterbroad.mult(6);
//Все завтраки:
  Rus food;
   food = chay.add(buterbroad);
// сколько денег осталось после завтраков
  mymoney = startMoney.minus(food);
// Сколько будет после получения денег в воскресенье:
  mymoney = mymoney.add(gift);
  mymoney.print();

}

получилось очень длинно и неудобно. Пришлось вводить дополнительные переменные для вычисления денег за еду.

Чтобы решение подобных задач было удобно можно переопределить действия уже известных операторов

В C++ есть операторы. Например, + - сложение, - - вычитание, * - умножение, / - деление, ! - отрицание и другие. C++ знает порядок их выполнения, умеет работать со скобками, если в них есть операторы.

Для каждого оператора в С++ определены действия с разными типами объектов. Например, + складывает любые числа как числа. Но строки они присоединяет друг к другу. Для классов, которые определены нами, действия с операторами не определены. То есть, объкты класса Money нельзя просто так складывать.

В С++ можно назначить любые действия с операторами для любых классов. Операторы программируются как обычные функции.

// Начало мантры
#include <iostream>
#include <cstdlib>
using namespace std;
// Конец мантры

class Rus{

  int R; // рубли
  int kop; // копейки
 public:
   Rus();
// функция получает деньги с клавиатуры
  void getMoney();

// Переопределение оператора +
// operator+ - это его ПОЛНОЕ название.
// operator+ всегда имеет два АРГУМЕНТА - правый и левый
// left + right
// operator+ всегда ВОЗВРАЩАЕТ значение
  Rus operator+(Rus money);

  void print();

};
//______________Реализация функций_______________

// Конструктор
Rus::Rus(){
  R=0;
  kop=0;
};

// получение значений с клавиатуры
void Rus::getMoney(){
   int kp;  // kp  только для getMoney()
   int R1, kop1; // только для getMoney()
   cin>>R1>>kop1;
       kp = R1*100+kop1;  //  все перевели в копейки
       R = kp /100;  // сколько всего получилось рублей
       kop = kp %100; // сколько всего получилось копеек
};

// печать
void Rus::print(){
  cout<<R<<" руб. "<<kop<<" коп."<<endl;
};

// опрератор +
Rus Rus::operator+(Rus money){
// Реализация такая же как и для функции add()

   Rus tmp; // место для подсчета денег      
// Считаем все в копейках:
   tmp.kop = (R *100 + kop); // наши деньги
// Добавили money 
   tmp.kop = tmp.kop + money.R * 100 + money.kop;
// Считаем рубли
   tmp.R = tmp.kop / 100;
// обычные копейки
   tmp.kop = tmp.kop % 100;  

// Возвращаем посчитанные деньги
   return tmp;
};

// Здесь нужен код для функций
int main(){
// примеры сложения
   Rus m1,m2,result;
// Значения с клавиатуры
   m1.getMoney();
   m2.getMoney();

// сложение 
//1. Длинный неудобный способ:
// использование ПОЛНОГО имени
   result = m1.operator+(m2);
   result.print(); 

//2. Короткий УДОБНЫЙ способ
  result = m1 + m2;
  result.print();  
}

REFACTOR Задача1

Написать код для ВСЕХ функций и решить задачу про чай и бутерброды. Функции проверять отдельно от решения задачи.

// Начало мантры
#include <iostream>
#include <cstdlib>
using namespace std;
// Конец мантры

class Rus{

  int R; // рубли
  int kop; // копейки
 public:
   Rus();
// функция получает деньги с клавиатуры
  void getMoney();

// Переопределение оператора +
// operator+ - это его ПОЛНОЕ название.
// operator+ всегда имеет два АРГУМЕНТА - правый и левый
// left + right
// operator+ всегда ВОЗВРАЩАЕТ значение
   Rus operator+(Rus money);

// Переопределение оператора -
   Rus operator-(Rus money);

// Переопределение оператора умножение
   Rus operator*(int n);

// Переопределение оператора деление 
   Rus operator/(int n);

   void print();

};
//______________Реализация функций_______________

// Здесь нужно написать код для всех функций
Rus::Rus(){
 // здесь нужен код
};

// получение значений с клавиатуры
void Rus::getMoney(){
   // здесь нужен код
};

// печать
void Rus::print(){
  cout<<R<<" руб. "<<kop<<" коп."<<endl;
};

// опрератор +
Rus Rus::operator+(Rus money){
// Реализация такая же как и для функции add()

   Rus tmp; // место для подсчета денег      
// Считаем все в копейках:
   tmp.kop = (R *100 + kop); // наши деньги
// Добавили money 
   tmp.kop = tmp.kop + money.R * 100 + money.kop;
// Считаем рубли
   tmp.R = tmp.kop / 100;
// обычные копейки
   tmp.kop = tmp.kop % 100;  

// Возвращаем посчитанные деньги
   return tmp;
};

// Оператор минус (-)
Rus Rus::operator-(Rus money){
 // здесь нужен код
};

// Оператор умножения *
Rus Rus::operator*(int n){
// здесь нужен код
};
 
// Оператор сложения /
Rus Rus::operator/(int n){
// здесь нужен код
};
int main(){
// примеры сложения
   Rus startmoney; //деньги вначале
   Rus chay; // цена чая
   Rus buterbroad; // цена бутерброда
   Rus gift; //полученные деньги
   Rus result;
// Значения с клавиатуры
   startmoney.getMoney();
   chay.getMoney();
   buterbroad.getMoney();
   gift.getMoney();

// Одна формула
  result = startmoney-(chay*6+buterbroad*6)+gift;
// Или 
  result = startmoney-(chay+buterbroad)*6+gift;
  result.print();  
}

REFACTOR Задача 2

У студента в начале месяца (30 дней) было rub рублей, kop копеек. Каждый день он покупал завтрак, обед и ужин. Ужин стоил в два раза дороже завтрака, а обед - в три. В конце месяца осталось r рублей, k копеек.

Написать программу, котрая вычисляет сколько стоил завтрак, обед и ужин. Использовать класс Rus из прошлой задачи со всеми функциями.

Слова

Операторы +, *, -, / можно переопределить не только для чисел.

Для строк уже определен оператор +. Можно определить класс Word, в котором мы научим оператор * увеличивать строку в N раз и оператор !, который "перевернет" строку.

// Начало мантры
#include <iostream>
#include <cstdlib>
using namespace std;
// Конец мантры

class Word{
 string s;

 public:
   Word();
   Word(string ss);
// функция получает текст с клавиатуры
  void getText();
//сложение слов abc+bds -> abcbdf
  Word operator+(Word a);

// умножение на число: az -> azazaza
  Word operator*(int n );

// оператор ! пишется СЛЕВА от объекта
// Этому оператору нужет только ОДИН параметр.
// Сам наш объект и будет параметром
   Word operator!();
   void print();
};
//______________Реализация функций_______________________

// Конструктор
Word::Word(){
  s.clear(); // строка стала пустой
};
// Конструктор с парметром
Word::Word(string ss){
  s=ss;
};
//получить текст с клавиатуры
void Word::getText(){
     cin>>s;
};
// печать 
void Word::print(){
  cout<<s<<endl;
};
// Оператор +
Word Word::operator+(Word a){
  //здесь нужен код
};
// Оператор ! 
// У оператора ! только один аргумент
// Это наш объект, с которым работаем

Word Word::operator!(){
    Word tmp;
    tmp.s=s;
 // Длина строки:
   int len;
   len=tmp.s.length();
// Номер последней буквы
   int last=len-1;
// Середина слова
   int middle=len/2;
   
// Меняем местами буквы с начала слова в конец
   for(int i=0; i<middle;i++){
     char t=tmp.s[i];
     tmp.s[i] = tmp.s[last-i];
     tmp.s[last - i] = t;    
   }   

   return tmp;
};
Word Word::operator*(int n){
   //здесь нужен код
};


int main(){
  Word slovo1,slovo2, res;
  slovo1.getText();
  slovo2.getText();
// Переворачиваем слово
  res= !slovo;
  res.print();
// Присоединяем слово
  res=res+slovo2;
  res.print();

  res = (slovo1 + !slovo2)*2;
  
  res.print();
  
}

REFACTOR задача 3

Дописать код для операторов + и *. Проверить работу всех операторов.

REFACTOR задача 4

Даны два слова top и AwA. Написать программу, которая получает из них вот такое слово:

toppotAwAtoppotAwAtoppotAwAAwAtoppotAwAtoppotAwAtoppot

Использовать класс Word. Код программы (main) должен быть как можно короче.

REFACTOR Задача 5

# Класс Оператор Студент
1 Rus <  
2 Rus >  
3 Rus Rus < int  
4 Word ==  
5 Word !=  
6 Word >  
7 Word <  
8 Word >=  
9 Word <= </td>  

Next: Word <= len -- TatyanaOvsyannikova2011 - 22 Oct 2015