Розробка класу, в якому продемонстровано реалізацію виключної ситуації переповнення
У даній темі розглянуто приклад того, як можна реалізувати клас, що обробляє виключну ситуацію переповнення з допомогою інструкції try…catch. За даним прикладом можна навчитись розробляти власні класи, що використовують механізм виключень C++ для обробки виключних ситуацій.
Зміст
Пошук на інших ресурсах:
Умова задачі
Розробити клас Int, який веде себе як вбудований int, тільки він ще генерує виключення у випадках переповнення. Умова задачі взята з книги Б. Страуструпа “Язык программирования C++”.
Особливості реалізації
У класі Int, з метою демонстрації реалізовано використання механізму виключень C++ для запобігання переповнення.
Для вбудованого типу int переповнення може виникати у наступних ситуаціях:
- під час створення об’єкту класу. У конструкторі класу може бути встановлене неправильне значення;
- під час операції присвоєння деякого значення. Це значення може бути некоректним;
- під час додавання (віднімання) двох об’єктів типу Int. Сума об’єктів може перевищити максимально (мінімально) допустиме, у результаті чого виникне переповнення;
- під час множення двох об’єктів типу Int між собою;
- інші ситуації, які можна реалізувати. Наприклад, множення об’єкту типу Int на деяке число, піднесення об’єкту типу Int в степінь, інкремент, декремент і т.д.
Щоб перехопити переповнення для вбудованого типу int, в класі Int використовується робота з типом long, який має більший діапазон значень (займає більше пам’яті) додатніх та від’ємних величин.
Клас Int реалізовано для 16-розрядних значень типу int.
⇑
Виконання
З метою демонстрації, в класі Int реалізовано такі функції:
- конструктор за замовчуванням;
- конструктор з одним параметром. У конструкторі використовується інструкція try…catch для перевірки на коректність значення параметру;
- операторна функція operator=(Int&), яка перевантажує оператор присвоєння =. Ця функція використовується для присвоювання об’єктів типу Int;
- перевантажена операторна функція operator=(long), яка перевантажує оператор присвоєння =. Ця функція використовується для присвоювання деякого значення об’єкту класу Int. У цій функції використовується блок try…catch;
- операторна функція operator+(Int), яка перевантажує оператор додавання +. У цій функції використовується блок try…catch;
- операторна функція operator*(Int), яка перевантажує оператор множення *. Функція використовує механізм try…catch для перевірки коректності значення результату множення;
- глобальна “дружня” (friend) операторна функція operator<<(), яка перевантажує оператор виведення в потік <<. Функція призначена для виведення об’єктів класу Int. Функція реалізована з демонстраційною метою;
- глобальна “дружня” (friend) операторна функція operator>>(), яка перевантажує оператор введення >> з потоку. Функція призначена для введення об’єктів класу Int і реалізована з демонстраційною метою.
Для визначення максимально допустимого та мінімально допустимого значення вбудованого типу int, у класі Int використовуються константи INT16_MIN та INT16_MAX. За бажанням можна вибрати інші константи (наприклад INT32_MIN, INT32_MAX).
Реалізація класу Int наступна:
#include <iostream> using namespace std; // Задача. Б.Страуструп class Int { private: long value; public: // Конструктори класу Int() { value = 0L; } Int(long _value) { try // перевірка { if ((_value < INT16_MIN) || (_value > INT16_MAX)) throw "Constructor. Exception: overflow."; value = _value; } catch (const char* e) // перехоплення виключення { // обробити виключення value = 0L; cout << e << endl; } } // Операторна функція, що перевантажує оператор присвоєння =, // ця функція має дві перевантажені реалізації. // Реалізація 1. Int& operator=(Int& t) { // Тут перевірки на переповнення не потрібно, // оскільки значення в t вже приведене до нормальної форми (не містить переповнення) value = t.value; return *this; } // Реалізація 2. Int& operator=(const long _value) { // У цій реалізації операторної функції обов'язково потрібна перевірка try { if ((_value < INT16_MIN) || (_value > INT16_MAX)) throw "Assignment operator=(long). Exception overflow."; value = _value; } catch (const char* e) // перехоплення виключення { cout << e << endl; } return *this; } // Перевантаження оператора додавання + Int& operator+(Int i) { long t = value+i.value; try { if ((t < INT16_MIN) || (t > INT16_MAX)) // перевірка на переповнення throw "Addition: overflow. "; value = t; } catch (const char* e) // перехоплення виключення { cout << e << endl; } return *this; } // Перевантаження оператора множення, // тут потрібна перевірка на переповнення Int& operator*(Int i) { long t = value * i.value; try { if ((t < INT16_MIN) || (t > INT16_MAX)) // перевірка на переповнення throw "Addition: overflow. "; value = (long)t; } catch (const char* e) { cout << e << endl; } return *this; } // Перевантаження операторів <<, >> friend std::ostream& operator<<(std::ostream& stream, const Int& i); friend std::istream& operator>>(std::istream& stream, Int& i); }; // Глобальна функція, яка перевантажує оператор виведення << std::ostream& operator<<(std::ostream& stream, const Int& i) { stream << i.value; return stream; } // Глобальна функція, яка перевантажує оператор введення >> // тут параметр Int& i не константний std::istream& operator>>(std::istream& stream, Int& i) { long t = i.value; // зберегти старе значення try { stream >> i.value; if ((i.value < INT16_MIN) || (i.value > INT16_MAX)) throw "Input exception: overflow."; return stream; } catch (const char* e) { // Обробка виключення. Відновити старе значення i.value = t; cout << e << endl; } } void main() { // Тест для класу Int Int i = 500000; // у конструкторі генерується виключення Int t = 300; // виключення не генерується cout << "i = " << i << endl; cout << "t = " << t << endl; cout << "i = t" << endl; i = t; // виклик операторної функції operator=(Int&) cout << "i = " << i << endl; i = 500; // cout << "i = " << i << endl; cout << endl << "Input i: "; cin >> i; cout << "After input: i = " << i << endl; // оператор присвоєння operator=(int) cout << "--------------------" << endl; cout << "i = 50000" << endl; i = 50000; cout << "i = " << i << endl; i = t = 3000; cout << "-----------------" << endl; cout << "i = t = 3000" << endl; cout << "i = " << i << endl; cout << "t = " << t << endl; cout << "------------" << endl; cout << "25000+15000 = 40000" << endl; i = 25000; t = 15000; t = t + i; cout << "t = " << t << endl; cout << "------------" << endl; cout << "i = 5; t = 220;" << endl; i = 5; t = 220; cout << t * i << endl; }
За даним зразком у класі Int можна реалізувати інші функції.
⇑