Классы в С++
"Перегрузка операторов."
Числа
Задача про покупкиУ человека утром в понедельник были деньги Rub рублей и kop копеек.
По утрам он заходил в кафе, выпивал N чашек чаю и съедал K бутербродов. Чай стоил chr рублей и ckop копеек, а бутерброд - br рублей и bkop копеек. Человек заходил в кафе каждый день кроме воскресенья.
В воскресенье он получил деньги giftr рублей и giftkop копеек. После этого человек решил вычислить сколько у него всего денег.
Написать программу, которая вычисляет количество денег в воскресенье вечером.
Решение
Если бы все цены били бы только в рублях, вычислить деньги было бы очень легко. Достаточно написать формулу:
Но есть еще и копейки. Мы уже умеем программировать класс 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(); }
Задача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(); }
Задача 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(); }
задача 3
Дописать код для операторов + и *. Проверить работу всех операторов.
задача 4
Даны два слова top и AwA. Написать программу, которая получает из них вот такое слово:
toppotAwAtoppotAwAtoppotAwAAwAtoppotAwAtoppotAwAtoppot Использовать класс Word. Код программы (main) должен быть как можно короче.
Задача 5
# | Класс | Оператор | Студент |
---|---|---|---|
1 | Rus | < | |
2 | Rus | > | |
3 | Rus | Rus < int | |
4 | Word | == | |
5 | Word | != | |
6 | Word | > | |
7 | Word | < | |
8 | Word | >= | |
9 | Word | <= </td> |