§ 3. Перагрузка аперацый
Практыкаваннi
1. Для праграмы з прыкладу 3.5 выканайце наступнае:
- Дапоўніце апісанне класа, прыведзенае ў прыкладах 3.7 і 3.9, перагрузкай аператараў уводу і вываду.
- Змяніце функцыі для перагрузкі аператараў параўнання так, каб яны былі дружалюбнымі.
- Як будзе рэагаваць праграма, калі выкарыстоўваць знак «<» для параўнання даўжынi вектараў? Чаму?
- Перагрузіце аперацыі «<» і «!=».
- Перагрузіце аператар «*» яшчэ раз, лічачы, што ён выкарыстоўваецца і для знаходжання скалярнага памнажэння двух вектараў [1].
[1] Скалярным памнажэннем двух вектараў i
з'яўляецца лік
.
2. Для праграмы з прыкладу 3.6 выканайце наступнае:
- Рэалізуйце шматфайлавы праект, падзяліце аб'яву і вызначэнне класа. Стварыце файлы Matrix.h і Matrix.cpp.
- Дапоўніце апісанне класа перагрузкай аператараў уводу і вываду, прыведзенае ў прыкладах 3.8 і 3.10.
- Змяніце функцыі для перагрузкі аператараў параўнання так, каб яны былі дружалюбнымі.
- Перагрузіце аперацыю «==», якая будзе вяртаць true, у тым выпадку, калі матрыцы маюць аднолькавыя памеры і false у адваротным выпадку.
- * Перагрузіце аператар «*» яшчэ раз, лічачы, што ён выкарыстоўваецца і для знаходжання памнажэння матрыц[1]
[1] Аб тым, як памнажаць матрыцы, можна пачытаць тут: https://www.webmath.ru/poleznoe/formules_6_6.php.
- Прадэманструйце працу метадаў і аператараў апісанага класа.
3. Змяніце апісанне класа Parallelepiped (заданне 4, §2), дадаўшы перагрузку аператараў параўнання паралелепіпедаў па аб'ёме.
4. Дадайце ў клас Rect (заданне 6, §2) перагрузку аперацый «+» для атрымання найменшага прамавугольніка, які змяшчае два зададзеных прамавугольніка, і «*» — для атрымання прамавугольніка, які з'яўляецца агульнай часткай (перасячэннем) двух прамавугольнікаў.
5. Стварыць клас Drob. Канструктар прымае два лікі: лічнік і назоўнік дробу. Перагрузіць аперацыі: складанне, множанне, дзяленне, адніманне. Рэалізаваць метады: скарачэнне (выкарыстоўваць private функцыю для знаходжання НОД па алгарытме Еўкліда), пераклад звычайнага дробу ў дзесятковы. Прадэманстраваць працу ўсіх функцый класа і перагружаных аперацый на прыкладах.
6. Стварыць базавы клас Progressii і яе наследнікаў — арыфметычную і геаметрычную прагрэсіі. Рэалізаваць метады: n-ы член прагрэсіі, праверка прагрэсіі на спаданне. Перагрузіць аперацыі: «+» (першы аперанд — пераменная тыпу прагрэсіі, другі — лік (колькасць элементаў)) для вылічэння сумы арыфметычнай прагрэсіі «*» — аналагічна для вылічэння сумы геаметрычнай прагрэсіі. Прадэманстраваць працу ўсіх функцый класа і перагружаных аперацый на прыкладах.
7. Апісаць клас Polinom для працы з мнагачленамі. Палямі класа з'яўляецца ступень мнагачлена і масіў каэфіцыентаў. Перагрузіць аперацыі «+», «-», «*», а таксама ўвод і вывад мнагачлена. Рэалізаваць метад вылічэння значэння мнагачлена для зададзенага значэння пераменнай[1]. *Выкарыстоўваючы метад двайковага дзялення, знайсці корань мнагачлена на зададзеным прамежку (корань павінен быць на гэтым прамежку адзіным).
[1] Рэкамендуецца выкарыстоўваць для вылічэння значэння мнагачлена схему Горнэра — https://intuit.ru/studies/professional_retraining/941/courses/67/lecture/1966?page=2
8*. Апісаць клас BigNumber для працы з «вялікімі» лікамі (лікі, якія не змяшчаюцца ў стандартныя тыпы). Перагрузіць аперацыі «+», «-», «*», параўнання, уводу і вываду.
Прыклад апісання некаторых членаў класа:
///Клас "вялікi лік", апісвае спосаб захоўвання вялікага ліку і складанне
class BigNumber
{
private:
vector < int > cifr;
///нармалізацыя ліку мадэлюе перанос у наступны разрад, калі лічба > 10
void norm();
public:
///Канструктар па змоўчанні ("пусты" лік)
BigNumber() {};
///Канструктар, канвертуе радок у вялікi лік
BigNumber(string str)
BigNumber operator + (const BigNumber &);
friend ostream & operator << (ostream &, const BigNumber &);
};
BigNumber::BigNumber(string str)
{
///Запісваем лічбы з канца радка
for (int i = str.size() - 1; i >= 0; i --)
cifr.push_back(str[i] - '0');
}
///Аператар +, выконвае складанне вялікіх лікаў
BigNumber BigNumber::operator + (const BigNumber &num)
{
BigNumber res;
int r1 = min(cifr.size(), num.cifr.size());
res.cifr.resize(r1);
/// складанне лічбаў
for (int i = 0; i < r1; i++)
res.cifr[i] = cifr[i] + num.cifr[i];
///калі ў адным з лікаў лічбы скончыліся
for (int i = r1; i < cifr.size(); i++)
res.cifr.push_back(cifr[i]);
for (int i = r1; i < num.cifr.size(); i++)
res.cifr.push_back(num.cifr[i]);
res.norm();
return res;
}
void BigNumber::norm()
{
if (cifr.size() > 1) {
for (int i = 0; i < cifr.size()-1; i++) {
cifr[i + 1] += cifr[i] / 10;
cifr[i] = cifr[i] % 10;
}
if (cifr[cifr.size() - 1] >= 10) {
int t = cifr[cifr.size() - 1] / 10;
cifr[cifr.size() - 1] = cifr[cifr.size() - 1] % 10;
cifr.resize(cifr.size() + 1);
cifr[cifr.size()-1] = t;
}
}
}
///Перагрузка аператара << для вываду
ostream & operator << (ostream &cout_bn, const BigNumber &num)
{
for (int i = num.cifr.size() - 1; i >= 0; i--)
cout_bn << num.cifr[i];
}
Прыклад выкарыстання:
int main() {
BigNumber n1("9999999999999999");
BigNumber n2("1");
cout << n1 << endl;
cout << n2 << endl;
BigNumber n3 = n1 + n2;
cout << n3 << endl;
return 0;