Menu
Coddy logo textTech

Обработка исключений в ООП

Часть раздела Объектно-ориентированное программирование путешествия по C++ на Coddy. Урок 81 из 104.

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

Базовый механизм использует три ключевых слова: try, throw и catch. Код, который might завершиться неудачей, помещается в блок try, ошибки обозначаются с помощью throw, а блоки catch обрабатывают определённые типы exception:

#include <iostream>
#include <stdexcept>

class BankAccount {
    double balance;
public:
    BankAccount(double b) : balance(b) {}
    
    void withdraw(double amount) {
        if (amount > balance) {
            throw std::runtime_error("Insufficient funds");
        }
        balance -= amount;
    }
    
    double getBalance() const { return balance; }
};

int main() {
    BankAccount account(100.0);
    
    try {
        account.withdraw(150.0);
    } catch (const std::runtime_error& e) {
        std::cout << "Error: " << e.what() << "\n";
    }
    
    std::cout << "Balance: " << account.getBalance() << "\n";
}

Стандартная библиотека C++ предоставляет иерархию классов исключений, корнем которой является std::exception. К распространённым производным классам относятся std::runtime_error для ошибок времени выполнения и std::logic_error для ошибок в программе. Все стандартные exceptions предоставляют what() method, который возвращает сообщение об ошибке.

Когда выбрасывается exception, стек разворачивается — вызываются деструкторы всех локальных объектов, пока программа ищет соответствующий блок catch. Это обеспечивает корректную очистку даже при возникновении ошибок, поэтому RAII и обработка exception так хорошо работают вместе.

challenge icon

Задание

Легко

Давайте создадим безопасный калькулятор деления, демонстрирующий обработку исключений в объектно-ориентированном контексте. Вы создадите Calculator class, который выполняет операции деления и выбрасывает понятные исключения, когда что-то идёт не так, а затем корректно обработаете эти исключения в своей основной программе.

Вы организуете свой код в трёх файлах:

  • Calculator.h: Define ваш Calculator class, который выполняет математические операции с proper обработкой ошибок.

    Ваш Calculator should have a method divide(double numerator, double denominator), который возвращает результат деления. Однако если denominator равен нулю, он должен выбросить std::runtime_error с message Division by zero. Если either numerator, либо denominator отрицателен, он должен выбросить std::invalid_argument с message Negative values not allowed.

    Также include a method safeSqrt(double value), который возвращает квадратный корень value. Если value отрицателен, выбросите std::runtime_error с message Cannot compute square root of negative number. Вам потребуется include <cmath> для функции sqrt.

  • Calculator.cpp: Implement методы, объявленные в вашем заголовочном файле. Убедитесь, что include необходимые заголовочные файлы (<stdexcept> и <cmath>) и проверьте условия перед выполнением операций.
  • main.cpp: Считайте три inputs (каждый в отдельной строке):
    1. Тип операции: either divide or sqrt
    2. Первое число (double)
    3. Второе число (double): используется только для деления, пропускается для sqrt

    Create объект Calculator и выполните запрошенную операцию внутри try block. Если операция выполнена успешно, выведите Result: [value]. Если исключение поймано, выведите Error: [message], где message берётся из метода what() исключения.

    After блока try-catch (независимо от того, произошло ли исключение), выведите Calculation complete, чтобы продемонстрировать, что программа продолжает выполнение после обработки исключений.

Например, с inputs divide, 10 и 2:

Result: 5
Calculation complete

С inputs divide, 10 и 0:

Error: Division by zero
Calculation complete

С inputs divide, -5 и 2:

Error: Negative values not allowed
Calculation complete

С inputs sqrt, 16 и 0:

Result: 4
Calculation complete

С inputs sqrt, -9 и 0:

Error: Cannot compute square root of negative number
Calculation complete

Обратите внимание, как программа корректно обрабатывает ошибки, перехватывая исключения и отображая понятные сообщения, а затем продолжает выполнение. Этот шаблон поддерживает чистую обработку ошибок, а вашу основную логику сосредоточенной на основном успешном сценарии.

Попробуйте сами

#include <iostream>
#include <string>
#include "Calculator.h"

using namespace std;

int main() {
    // Читаем входные данные
    string operation;
    double num1, num2;
    
    cin >> operation;
    cin >> num1;
    cin >> num2;
    
    // Создаём объект Calculator
    Calculator calc;
    
    // TODO: Используйте блок try-catch для выполнения операции
    // - Если operation равно "divide", вызовите calc.divide(num1, num2)
    // - Если operation равно "sqrt", вызовите calc.safeSqrt(num1)
    // - При успехе выведите "Result: " за которым следует результат
    // - Перехватывайте исключения и выводите "Error: " за которым следует сообщение исключения (используйте what())
    // - After the try-catch, always print "Calculation complete"
    
    
    return 0;
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор C++