С++. Пример создания иерархии классов для обработки исключительных ситуаций

Пример создания иерархии классов для обработки исключительных ситуаций

В примере создается собственная иерархия классов, которая обрабатывает разные арифметические исключительные ситуации. Для демонстрации выбрано только несколько классов обрабатывающих исключительные ситуации. По собственному усмотрению можно расширить перечень исключительных ситуаций подлежащих обработке, например, логарифм с нуля, тангенс 90 градусов и прочее. По данному примеру можно научиться создавать собственные иерархии классов обработки исключительных ситуаций в C++.


Содержание


1. Текст демонстрационного примера для приложения типа Console Application

Пример демонстрирует обработку исключительных ситуаций:

  • деление на нуль;
  • отрицательный индекс в массиве.

 

#include <iostream>
#include <string>
using namespace std;

// Создание иерархии классов, обрабатывающих исключения
// абстрактный базовый класс, создать объект класса невозможно
class BaseException
{
protected:
  // объяснение к исключению - общее для всех производных классов
  string text;

public:
  // чистая виртуальная функция, которая выводит текст исключения
  virtual string what() = 0;
};

// класс, который соответствует арифметическим операциям
class ArithmeticException :public BaseException
{
public:
  // конструкторы класса
  // конструктор по умолчанию
  ArithmeticException()
  {
    text = "Error. Arithmetic Exception.";
  }

  // конструктор с заданным текстом
  ArithmeticException(string _text) { text = _text; }

  // переопределяем виртуальную функцию what() - обязательно
  string what() { return text; }
};

// разновидность класса ArithmeticException - деление на 0,
// поскольку класс есть внизу иерархии и из него унаследовать ничего уже
// нельзя, то объявление класса содержит спецификатор final
class DivideByZero final :public ArithmeticException
{
public:
  // конструктор, который содержит текст описывающий данное исключение
  DivideByZero() :ArithmeticException()
  {
    text = "Divide by zero."; // текст по умолчанию
  }

  // конструктор, который получает строку текста от пользователя
  DivideByZero(string _text) :ArithmeticException(_text)
  {    
  }

  string what()
  {
    return text;
  }
};

// разновидность класса BaseException
// отрицательный индекс в массиве
// это также final-класс
class NegativeIndex final :public BaseException
{
public:
  // конструктор получает аргумент по умолчанию
  NegativeIndex(string _text = "Error. Negative Index.") { text = _text; }

  // обязательно нужно переопределить функцию what()
  string what() { return text; }
};

  // Демонстрационная функция для класса NegativeIndex
void DemoExceptions1()
{
  int a[10];
  int index;

  for (int i = 0; i < 10; i++)
    a[i] = i * i;
  cout << "Input index: " << endl;
  cin >> index;

  // проверка индекса на отрицательное значение
  if (index < 0)
    throw NegativeIndex(); // сгенерировать исключение типа NegativeIndex
  cout << "a[" << index << "] = " << a[index] << endl;
}

// Демонстрационная функция для класса ArithmeticException
void DemoExceptions2()
{
  int a, b, c;
  cout << "a = "; cin >> a;
  cout << "b = "; cin >> b;

  // делить на 0 запрещено
  if (b == 0)
    throw DivideByZero("Divide by 0.");
  cout << "a / b = " << (double)a / b << endl;
}

void main()
{
  try
  {
    // вызвать функцию, генерирующую исключение
    DemoExceptions1(); // проверка на "Negative Index"
    DemoExceptions2(); // проверка на "Divide by 0"
    cout << "OK!" << endl;
  }
  catch (NegativeIndex e)
  {
    // обработать исключение
    cout << e.what() << endl;
  }
  catch (DivideByZero e)
  {
    cout << e.what() << endl;
  }
}

 



2. Объяснение к работе программы. Схема иерархии классов

В примере создается абстрактный базовый класс BaseException в котором объявляются:

  • строка text типа string, которая есть объяснением к исключительной ситуации;
  • чистая виртуальная функция what() предназначенная для вывода строки text на экран.

Из класса BaseException наследуется класс ArithmeticException, предназначенный для обработки арифметических исключительных ситуаций. Из класса ArithmeticException наследуются два класса:

  • класс DivideByZero – предназначен для обработки исключительной ситуации деления на ноль;
  • класс NegativeIndex – предназначен для обработки исключительной ситуации отрицательного индекса из массива.

Общая схема реализованных классов изображена на рисунке.

C++. Схема реализованных классов исключений

 

3. Возможность наследования от класса exception

В примере объявляется собственный базовый класс BaseException. Рекомендуется собственные классы обработки исключительных ситуаций наследовать от класса exception библиотеки C++. То есть, более правильно было бы объявить класс BaseException следующим образом:

// класс BaseException унаследован от класса exception
class BaseException: public exception
{
protected:
  string text; // объяснение к исключению - общее для всех производных классов

public:
  virtual string what() = 0; // чистая виртуальная функция, которая выводит текст исключения
};

 


Связанные темы