Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++Lecture-1-15.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
122.37 Кб
Скачать

Int main()

{ SetConsoleOutputCP(1251);

double x, y, z;

cout << "Введіть два числа: ";

while (cin>>x>>y)

{ try {

z = harmonic_4(x,y);

}

catch (DivByZero) {

cout << "Числа не можуть бути протилежними. Спробуйте ще.\n\n";

continue;

}

catch (ZeroArg)

{ cout << "Жодне з чисел не може бути нулем. Спробуйте ще.\n\n";

continue;

}

cout << "Середнє гармонійне чисел "<<x<<" та "<<y<<" є "<<z<<"\n\n"

<< "Введіть наступні два числа (або Q, щоб вийти): ";

} return 0;

}

double harmonic_4(double a, double b) throw(DivByZero,ZeroArg)

{ if (a==0 || b==0) throw ZeroArg();

if (a == -b) throw DivByZero();

return 2.0*a*b/(a+b);

}

Тут для позначення винятків оголошено класи DivByZero та ZeroArg. Вони не мають ніякої особливої функціональності, лише конструктори і деструктор, згенеровані компілятором. Та нам і цього вистачить, бо для потреб програми важливим є тільки ім’я класу. Інструкція throw запускає як виняток безіменний екземпляр класу, створений конструктором за замовчуванням. Блок catch впізнає тип винятка і перехоплює його.

На ті класи, які використовують для позначення винятків, розповсюджуються ті самі правила, що й на всі інші класи: вони можуть утворювати ієрархію за відношенням наслідування, їх можна оголошувати всередині інших класів тощо. Досить часто класи винятків оголошують всередині тих класів, яким вони допомагають боротися з помилками. Це явно вказує на їхнє призначення та запобігає конфліктові імен.

На попередніх лекціях ми створили клас ArrayDb, що інкапсулює динамічний масив дійс­них чисел. Удосконалимо його, застосувавши механізм винятків для захисту конструкторів від неправильно заданого розміру масиву та оператори індексування від неправильно заданого номера елемента масиву. Новий клас назвемо ArrayDbE.

// Заголовковий файл "arraydbe.h"

#include <iostream>

class ArrayDbE

{private: unsigned int size;

protected: double* arr;

public:

class BadSize {}; // позначатиме неправильний розмір масиву

class BadIndex { // позначатиме виняток "неправильний індекс", а також

public: // міститиме його значення, буде вміти його повідомити

int badInd;

BadIndex(int i): badInd(i) {}

virtual void report() const;

};

ArrayDbE(): arr(0), size(0) {}

explicit ArrayDbE(unsigned int n, double val = 0.0) throw(BadSize);

ArrayDbE(const double* pn, unsigned int n) throw(BadSize);

ArrayDbE(const ArrayDbE& a);

virtual ~ArrayDbE();

unsigned int arSize() const { return size; }

double average() const;

double& operator[](int i) throw(BadIndex&);

const double& operator[](int i) const throw(BadIndex&);

ArrayDbE& operator=(const ArrayDbE& a);

friend std::ostream& operator<<(std::ostream& os, const ArrayDbE& a);

};

Реалізація методів

#include <iostream>

#include "arraydbe.h"

// функціональність об’єкта-винятка

void ArrayDbE::BadIndex::report() const

{ std::cerr << "Out of bounds index value: " << badInd << '\n';

}

// захищені конструктори

ArrayDbE::ArrayDbE(unsigned int n, double val) throw(BadSize)

{ if (n<0 || n>32000) throw BadSize();

arr = new double[n];

size = n;

for (size_t i=0; i<n; i++) arr[i] = val;

}

ArrayDbE::ArrayDbE(const double *pn, unsigned int n) throw(BadSize)

{ if (n<0 || n>32000) throw BadSize();

arr = new double[n];

size = n;

for (size_t i=0; i<n; i++) arr[i] = pn[i];

}

// конструктор копіювання захисту не потребує

ArrayDbE::ArrayDbE(const ArrayDbE &a)

{ size = a.size;

arr = new double[size];

for (size_t i=0; i<size; i++) arr[i] = a.arr[i];

}

ArrayDbE::~ArrayDbE()

{ delete[] arr;

}

double ArrayDbE::average() const

{ if (size>0)

{ double sum = 0.0;

for (size_t i=0; i<size; i++) sum += arr[i];

return sum/size;

}

std::cerr << "No entries in score array\n";

return 0;

}

// захищені оператори

double& ArrayDbE::operator[](int i) throw(BadIndex&)

{ if ( i<0 || i>=size ) throw BadIndex(i);

return arr[i];

}

const double& ArrayDbE::operator[](int i) const

{ if ( i<0 || i>=size ) throw BadIndex(i);

return arr[i];

}

// решта – без змін

ArrayDbE& ArrayDbE::operator =(const ArrayDbE &a)

{ if (this == &a) return *this;

delete[] arr;

size = a.size;

arr = new double[size];

for (size_t i=0; i<size; i++) arr[i] = a.arr[i];

return *this;

}

ostream& operator<<(ostream& os, const ArrayDbE& a)

{ for (size_t i=0; i<a.size; i++)

{ os.width(8); os<<a.arr[i];

}

if (a.size % 10 != 0) os << '\n';

return os;

}

Приклад використання

#include <iostream>

#include "arraydbe.h"

using namespace std;

int Players = -3; // провокує виняток BadSize

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]