Разработка класса, демонстрирующего реализацию исключительной ситуации переполнения
В данной теме рассмотрен пример того, как можно реализовать класс, который обрабатывает исключительную ситуацию переполнения с помощью инструкции try…catch. По данному примеру можно научиться разрабатывать собственные классы, которые используют механизм исключений C++ для обработки исключительных ситуаций.
Содержание
Поиск на других ресурсах:
Условие задачи
Разработать класс Int, который ведет себя как встроенный int, только он еще генерирует исключение в случаях переполнения. Условие задачи взято из книги Б. Страуструпа «Язык программирования C++».
Особенности реализации
В классе Int, с целью демонстрации реализовано использование механизма исключений C++ для предотвращения переполнения.
Для встроенного типа int переполнение может возникать в следующих ситуациях:
- во время создания объекта класса. В конструкторе класса сразу может быть установлено неправильное значение;
- во время операции присваивания некоторого значения. Это значение может быть некорректным;
- во время суммирования (вычитания) двух объектов типа Int. Сумма объектов может превысить максимально (минимально) допустимое, в результате чего возникнет переполнение;
- во время умножения двух объектов типа Int между собой;
- другие ситуации, которые можно реализовать. Например, умножение объекта типа Int на некоторое число, возведение объекта типа Int в степень и т.д.
Чтобы перехватить переполнение для встроенного типа int, в классе Int используется работа с типом long, который имеет больший диапазон значений (занимает больше памяти) положительных и отрицательных величин. Соответственно можно производить необходимые проверки на превышение максимально (минимально) допустимого значения типа int.
Класс 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 следующая:
// Задача. Б.Страуструп 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 можно реализовать и другие функции.
⇑