
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