Печатать книгуПечатать книгу

§ 3. Перагрузка аперацый

Алгоритмические конструкции

Как вам уже известно из курса информатики, любой алгоритм может быть записан с использованием трех базовых алгоритмических конструкций: следование, цикл и ветвление (пример 3.1).

Команды, составляющие алгоритмическую конструкцию следование, выполняются последовательно, друг за другом, в том порядке, в котором они записаны. Команды цикла и ветвления управляют порядком выполнения других команд в программе и относятся к командам управления (управляющим конструкциями).

Алгоритмическая конструкция ветвления обеспечивает выполнение одной или другой последовательности команд в зависимости от истинности или ложности некоторого условия. Оператор ветвления — команда, реализующая алгоритмическую конструкцию ветвления на языке программирования.

Алгоритмическая конструкция повторение (цикл) представляет собой последовательность действий, выполняемых многократно. Саму последовательность называют телом цикла. Оператор цикла — это команда, реализующая алгоритмическую конструкцию повторения на языке программирования.

Существуют разные возможности управлять тем, сколько раз будет повторяться тело цикла. Может быть задано условие продолжения или окончания работы цикла, а также число повторений тела цикла. В зависимости от этого выделяют цикл с предусловием, цикл с постусловием и цикл с параметром.

Существуют разные возможности управлять тем, сколько раз будет повторяться тело цикла. Может быть задано условие продолжения или окончания работы цикла, а также число повторений тела цикла. Выделяют следующие циклы: цикл с предусловием, цикл с постусловием и цикл с параметром. Выбор цикла зависит от задачи. Во многих случаях циклы взаимозаменяемы. При выборе цикла можно ориентироваться на следующее:

  • цикл с параметром используется тогда, когда известно количество повторений;
  • цикл с предусловием используется в том случае, когда известно условие продолжения работы;
  • цикл с постусловием используется тогда, когда тело цикла должно быть выполнено хотя бы один раз.

Пример 3.1 Блок-схемы алгоритмических конструкций.

Следование

Ветвление

Цикл

  • Цикл с параметром (значение параметра изменяется от 1 до N):

  • Цикл с предусловием:

  • Цикл с постусловием:

Кроме блок-схем, для графического представления алгоритмов используют структурограммы (NS-диаграммы, диаграммы Насси — Шнейдермана).

Примеры структурограмм

Команда ветвления:

Команда цикла с предусловием:

Сайт: Профильное обучение
Курс: Інфарматыка. 11 клас (Павышаны ўзровень)
Книга: § 3. Перагрузка аперацый
Напечатано:: Гость
Дата: Вторник, 30 Апрель 2024, 11:38

3.1. Перагрузка арыфметычных аперацый

Перагрузка аператараў у праграмiраванні — адзін з спосабаў рэалізацыі палімарфізму. Яна дазваляе выкарыстоўваць некалькі розных варыянтаў прымянення аператара. Аператары маюць адно і тое ж імя, але адрозніваюцца тыпамі параметраў, да якіх яны ўжываюцца.

У мове C++ аператары рэалізаваны ў выглядзе функцый. Выкарыстоўваючы перагрузку функцыі аператара, вы можаце вызначыць свае ўласныя версіі аператараў, якія будуць працаваць з рознымі тыпамі даных, уключаючы класы.

З перагружанымі аператарамі вы ўжо працавалі. У класе string перагружаныя аператары параўнання і аператар «+». Для параўнання радкоў выкарыстоўваюцца тыя ж знакі, што і для параўнання лікаў, аднак параўнанне радкоў выконваецца не так, як параўноўваюцца лікі. Складанне радкоў таксама мае сэнс, які адрозніваецца ад складання лікаў.

Большасць аперацый у С++ можна перазагрузіць (прыклад 3.1)[1].

Важна памятаць, што перагрузка пашырае магчымасці мовы, а не змяняе мову. Таму нельга перагружаць аператары для ўбудаваных тыпаў даных. Нельга мяняць прыярытэт выканання аператараў і іх асацыятыўнасць (злева направа ці справа налева). Нельга ствараць уласныя аператары і перагружаць некаторыя ўбудаваныя (прыклад 3.2).

Сінтаксіс перагрузкі аперацый:

тып operator @ (спiс_параметраў-аперанд)
{
// цела функцыі
}

дзе @ — знак перагружанай аперацыі,

тып — тып значэння, якое вяртаецца.

Перагружаць можна толькі аперацыі, для якіх хоць бы адзін аргумент уяўляе тып даных, вызначаны карыстальнікам (напрыклад, клас). Функцыя для перагрузкі аперацыі павінна быць вызначана або як функцыя-член класа (прыклад 3.3), або як знешняя функцыя, але дружалюбная класу (пример 3.4). Адзін і той жа аператар можна перагрузіць некалькі разоў.

Калі бінарная[2] аперацыя перагружаецца з выкарыстаннем метаду класа, то першым аперандам яна атрымлівае пераменную класа, якая няяўна перадаецца праз паказальнік this на аб'ект. Другім аперандам з'яўляецца аргумент функцыі. Такім чынам, бінарная аперацыя, перагружаная метадам класа, мае фактычна адзін параметр (правы аперанд), а левы перадаецца няяўна праз паказальнік this.

Калі перагрузка бінарнай аперацыі рэалізавана з выкарыстаннем дружалюбнай функцыі, то ў спісе параметраў павінна быць два аргумента.

Прыклад 3.5. Вектар на плоскасці задаецца парай каардынат. Апісаць клас Vect для прадстаўлення вектара на плоскасці. Рэалізаваць метад, які вылічае даўжыню вектара, перагрузіць аператары «+» (складанне двух вектараў), «*» (множання вектара на лік), «==» (параўнанне вектараў), «>» (параўнанне вектараў па даўжыні).

Этапы выканання задання

1. Палямі класа будуць каардынаты (х, y) вектара на плоскасці.

2. Для вылічэння даўжыні вектара ў метадзе класа dl выкарыстоўваецца формула вылічэння даўжыні адрэзка.

3. Рэалізаваць перагрузку аперацый.

    1. Для перагрузкі аперацый ««==» і «>» трэба апісаць адпаведныя функцыі. Функцыі павінны мець тып bool. Функцыі рэалізаваць як метады класа.
    2. Для перагрузкі аперацыі «*» трэба апісаць адпаведную функцыю. Функцыя павінна мець тып Vect. Функцыю рэалізаваць як метад класа.
    3. Для перагрузкі аперацыі «+» рэалізаваць дружалюбную функцыю, якая вяртае тып Vect.

Любы перагружаны аператар можна выклікаць з выкарыстаннем функцыянальнай формы запісу (функцыі-аперацыі):

Vect v3 = operator + (v1, v2);

Выкарыстанне аперацыі — гэта ўсяго толькі скарочаны запіс яўнага выкліку функцыі аперацыі. Паколькі функцыя-аперацыя апісваецца так жа, як любая іншая функцыя, то і яна можа выклікацца аналагічна.

Прамавугольную табліцу з лікамі ў матэматыцы называюць матрыцай. Памер матрыцы вызначаецца колькасцю радкоў і слупкоў ў ёй. Для матрыц вызначаны арыфметычныя аперацыі. Матрыцу можна памножыць на лік — для гэтага кожны элемент матрыцы памнажаецца на яго. Дзве матрыцы аднолькавага памеру можна скласці ці адняць. Дзеянні выконваюцца над элементамі, якія стаяць на адпаведных месцах.

Прыклад 3.6. Апісаць клас Matrix. Перагрузіць аперацыі складання, аднімання і множання матрыцы на лік.

Этапы выканання задання

1.  Палямі класа будуць цэлыя лікі m, n — колькасць радкоў і слупкоў у матрыцы і двухмерны вектар для захоўвання самой матрыцы.

2. Рэалізаваць метад rand_data, які будзе запаўняць матрыцу выпадковымі лікамі.

3. Перагрузка аперацый аналагічная перагрузцы аперацый, якія рэалізаваны ў прыкладзе 3.4.

    1. Пры перагрузцы аперацыі множання на лік памножым на гэты лік кожны элемент матрыцы.
    2. Пры перагрузцы аперацыі «+» прасумуем элементы з аднолькавымі нумарамі радка і слупка.
    3. Пры перагрузцы аперацыі «-» скарыстаемся тым, што
      AB = A + B * (–1).

[1] Больш падрабязна аб перагрузцы аператараў можна пачытаць, напрыклад тут: https://habr.com/ru/post/489666/

[2] Аперацыя з'яўляецца бінарнай, калі для яе выканання неабходны два аперанда. Напрыклад, аперацыя складання (a + b). Аперацыя з адным аперандам з'яўляецца ўнарнай. Напрыклад, аперацыя змены знака ў ліку (-a).

Неабходнасць у перагрузкi аперацый абумоўлена патрэбай апісваць і ўжываць да створаных праграмістам тыпам даных аперацыі, па сэнсе эквівалентныя ўжо іcнуючым у мове.

Для рэалізацыі перагрузкі аперацый у мове праграмiравання неабходна ўвесці ў ім адпаведныя сінтаксічныя канструкцыі. Варыянтаў рэалізацыі можа быць шмат, аднак яны мала чым адрозніваюцца адзін ад аднаго. Дастаткова памятаць, што запіс выгляду

<аперанд1> <знакАперацыi> <аперанд2>

аналагічны выкліку функцыі <знакАперацыi>(<аперанд1>,<аперанд2>).

Калі дазволіць праграмісту апісваць паводзіны аператараў у выглядзе функцый, то праблема перагрузкі аператараў будзе вырашана.

Прыклад 3.1. Аперацыі, якія можна перагрузіць у С++:

+   -   *  /    %  ^   & |     ~  !    =  <  >  

+=     -=     *=      /=      %=    ^=     &=     |=

<<     >>    >>=    <<=   ==     !=     <=      >=

&&    ||       ++      --       []       ()

Прыклад 3.2. Аперацыі, якія нельга перагрузіць у С++:

  • аператар выбару члена класа «.»;
  • аператар разнаймення паказальніка на член класа «.*»;
  • тэрнарны аператар «? :»;
  • аперацыя ўказання вобласці бачнасці «::»;
  • аперацыя вылічэння памеру ў байтах sizeof.

Дружалюбная функцыя — гэта функцыя, якая не з'яўляецца членам класа, але якая мае доступ да яго закрытых членаў. Ёю можа быць як звычайная функцыя, так і метад іншага класа. Для аб'явы дружалюбнай функцыі выкарыстоўваецца ключавое слова friend перад аб'явай функцыі, якая стане дружалюбнай класу. Функцыя можа быць аб'яўлена як у раздзеле public, так і раздзеле private.

Прыклад 3.3. Перагрузка аперацыі «+» з прымяненнем метаду класа:

class Vect

{

  ...

public:

  Vect operator + (const Vect &);

  ...

};

Прыклад 3.4. Перагрузка аперацыі «+» з ужываннем знешняй функцыі, дружалюбнай класу:

class Vect

{

  ...

public:

  friend Vect operator + (Vect &, Vect &);

  ...

};

Прыклад 3.5. Праграма.

#include <iostream>

#include <math.h>

#include <windows.h>

 

using namespace std;

 

class Vect ///

клас, які апісвае вектар на плоскасці

{

    double x,y;

  public:

    ///канструктары класа

    Vect() {= 0; y = 0;}

    Vect (double z1, double z2):

             x(z1), y(z2) {}

 

    ///вяртанне каардынат

    double get_x(){return x;}

    double get_y(){return y;}

    ///даўжыня вектара

    double dl();

    /// аператар параўнання двух вектараў

    bool operator == (Vect &);

    /// аператар параўнання двух вектараў па даўжыні

    bool operator > (Vect &);

    /// аператар множання вектара на лік

    Vect operator *(int);

    ///аператар складання двух вектараў

    friend Vect operator +(Vect &, Vect &);

};

 

double Vect::dl()

{

  return sqrt(* x + y * y);

}

 

bool Vect::operator == (Vect &p)

{

  return  (== p.&& y == p.y);

}

 

bool Vect::operator > (Vect &p)

{

  return (dl() > p.dl()) ? true : false;

}

 

Vect Vect::operator *(int k)

{

  return Vect(* k, y * k);

}

 

Vect operator +(Vect &p, Vect &q)

{

  return Vect(p.+ q.x, p.+ q.y);

}

 

int main()

{

  SetConsoleCP(1251);

  SetConsoleOutputCP(1251);

  double a,b,c,d;

  cout << "каардынаты:" << endl;

  cin >> a >> b >> c >> d;

  Vect v1(a, b), v2(c, d);

  cout << "даўжыня 1-га = " ;

  cout << v1.dl() << endl;

  cout << "даўжыня 2-га = " ;

  cout << v2.dl() << endl;

  if (v1 == v2)

    cout << "вектары супадаюць" << endl;

  else

    cout << "вектары не  супадаюць" << endl;

  if (v1 > v2)

    cout << "даўжыня 1-га больш" << endl;

  else

    cout << "даўжыня 1-га не больш" << endl;

  Vect v3 = v1 + v2;

  cout << "каардынаты вектара v3: " ;

  cout << v3.get_x() << " ";

  cout << v3.get_y() << endl;

  cout << "даўжыня вектара v3 = ";

  cout << v3.dl() << endl;

  Vect v4 = v1 * 5;

  cout << "каардынаты вектара v4: ";

  cout << v4.get_x() << " ";

  cout << v4.get_y() << endl;

  cout << "даўжыня вектара v4 = " ;

  cout << v4.dl() << endl;

  return 0;

}

Вынік працы:

Роб Мюрэй, у сваёй кнізе «C++ Strategies and Tactics» рэкамендаваў перагружаць унарныя аперацыі і аперацыі, сумешчаныя з прысвойваннем (+=, *= і інш.), як члены класа. Бінарныя аперацыі ён рэкамендаваў перагружаць з выкарыстаннем дружалюбных функцый.

Прыклад 3.6. Апісанне класа Matrix.

class Matrix

{

    int n, m;

    vector < vector <int> > data;

  public:

    Matrix();

    Matrix(int n_, int m_);

    void rand_data ();

    Matrix operator + (Matrix &);

    Matrix operator * (int);

    Matrix operator - (Matrix &);

};

 

Matrix::Matrix()

{

    n = 1;  m = 1;

    data.resize(n);

    data[0].resize(m, 0);

}

 

Matrix::Matrix(int n_, int m_)

{

    n = n_;

    m = m_;

    data.resize(n);

    for (int i = 0; i < n; i++)

        data[i].resize(m, 0);

}

 

void Matrix::rand_data()

{

    for (int i = 0; i < n; i++)

      for (int j = 0; j < m; j++)

        data[i][j] = rand() % 100;

}

 

Matrix Matrix::operator + (Matrix &d)

{

    Matrix t(n, m);

    for (int i = 0; i < n; i++)

      for (int j = 0; j < m; j++)

         t.data[i][j] = data[i][j] +

                       d.data[i][j];

    return t;

}

 

Matrix Matrix::operator * (int k)

{

    Matrix t(n, m);

    for (int i = 0; i < n; i++)

      for (int j = 0; j < m; j++)

        t.data[i][j] = data[i][j] * k;

    return t;

}

 

Matrix Matrix::operator - (Matrix &d)

{

    Matrix t(n, m);

    t = d * (-1);

    t = *this + t;

    return t;

}

 

3.2. Лагічны тып даных

Для стандартных тыпаў даных такіх як int або double ўвод і вывад рэалізаваны праз стандартныя аператары >> і <<. Гэтыя ж аператары перагружаныя для ўводу-вываду радкоў. Для карыстальніцкіх тыпаў даных, якія маюць мноства палёў, таксама можна перагрузіць аператары ўводу-вываду. Перагрузка аператараў < < і >> нашмат спрашчае працэс вываду аб'екта на экран і атрыманне карыстальнiцкага ўводу з запісам даных у аб'ект класа.

Разгледзім перагрузку аператара <<. Аператар з'яўляецца бінарным аператарам, таму яго перагрузка будзе аналагічная перагрузцы аператара «+», разгледжанай у прыкладах 3.5 і 3.6. Левым аперандам у аператара < < з'яўляецца аб'ект cout, а правым — аб'ект класа, які трэба вывесці. Аператар, які перавызначаецца, павінен вяртаць значэнне тыпу ostream, аб'ектам якога з'яўляецца cout. Параметры, апісанай функцыі, павінны быць спасылкамі (прыклады 3.7 i 3.8). Таксама спасылкай павінен быць і вынік, які вяртаецца, паколькі ostream забараняе сваё капіраванне.

Перагрузка аператара ўводу адбываецца аналагічна. Адрозненне ў тым, што cin з'яўляецца аб'ектам тыпу istream (прыклады 3.9 i 3.10). Спасылка на аб'ект класа, які з'яўляецца другім параметрам, не можа быць канстантай, паколькі аб'ект змяняецца пры ўводзе.

Пасля перазагрузкі аператараў уводу і вываду іх можна выкарыстоўваць таксама для чытання і запісу файлаў.

Прыклад 3.7. Перагрузка аператара вываду << для класа Vect, вызначанага ў прыкладзе 3.5.

Аб'ява:

friend ostream & operator << 

(ostream &, const Vect &);

Апісанне:

ostream & operator << 

(ostream &out, const Vect &p)

{

  out << p.<< " " << p.<< endl;

}

Прыклад 3.8. Перагрузка аператара вываду << для класа Matrix, вызначанага ў прыкладзе 3.6.

Аб'ява:

friend ostream & operator << 

(ostream &, const Matrix  &);

Апісанне:

ostream & operator << 

(ostream & out, const Matrix &d)

{

  for (int i = 0; i < d.n; i++){

    for (int j = 0; j < d.m; j++)

      out << setw(4) << d.data[i][j];

    out << endl;

  }

  out << endl;

Прыклад 3.9. Перагрузка аператара вываду >> для класа Vect, вызначанага ў прыкладзе 3.5.

Аб'ява:

friend istream & operator >> 

(istream &, Vect &);

Апісанне:

span style="font-size: medium;">istream & operator >> 
(istream &in, Vect &p)

{

    in >> p.>> p.y;

}

Прыклад 3.10. Перагрузка аператара вываду >> для класа Matrix, вызначанага ў прыкладзе 3.6

Аб'ява:

friend istream & operator >> 

(istream &, Matrix &);

Апісанне:

istream & operator >> 

(istream & in, Matrix &d)

{

  for (int i = 0; i < d.n; i++)

    for (int j = 0; j < d.m; j++)

      in >> d.data[i][j];

}

Пытаннi да параграфа

1. Для чаго выкарыстоўваецца перагрузка аперацый?

2. Якія аперацыі можна перагрузіць у С++?

3. Якія аперацыі нельга перагрузіць у С++?

4. Якімі спосабамі можна вызначыць функцыю для перагрузкі аператараў?

 

Практыкаваннi

 

1. Для праграмы з прыкладу 3.5 выканайце наступнае:

    1. Дапоўніце апісанне класа, прыведзенае ў прыкладах 3.7 і 3.9, перагрузкай аператараў уводу і вываду.
    2. Змяніце функцыі для перагрузкі аператараў параўнання так, каб яны былі дружалюбнымі.
    3. Як будзе рэагаваць праграма, калі выкарыстоўваць знак «<»  для параўнання даўжынi вектараў? Чаму?
    4. Перагрузіце аперацыі «<» і «!=». 
    5. Перагрузіце аператар «*» яшчэ раз, лічачы, што ён выкарыстоўваецца і для знаходжання скалярнага памнажэння двух вектараў [1].


[1] Скалярным памнажэннем двух вектараў   i   з'яўляецца лік .

2. Для праграмы з прыкладу 3.6 выканайце наступнае:

    1. Рэалізуйце шматфайлавы праект, падзяліце аб'яву і вызначэнне класа. Стварыце файлы Matrix.h і Matrix.cpp.
    2. Дапоўніце апісанне класа перагрузкай аператараў уводу і вываду, прыведзенае ў прыкладах 3.8 і 3.10.
    3. Змяніце функцыі для перагрузкі аператараў параўнання так, каб яны былі дружалюбнымі.
    4. Перагрузіце аперацыю «==», якая будзе вяртаць true, у тым выпадку, калі матрыцы маюць аднолькавыя памеры і false у адваротным выпадку.
    5. * Перагрузіце аператар «*» яшчэ раз, лічачы, што ён выкарыстоўваецца і для знаходжання памнажэння матрыц[1]

      [1] Аб тым, як памнажаць матрыцы, можна пачытаць тут: https://www.webmath.ru/poleznoe/formules_6_6.php.

    6. Прадэманструйце працу метадаў і аператараў апісанага класа.

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[+ 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;