19. Exception and Classes in C++

Introduction

In C++, Exception Handling is a process that responds to anomalous or exceptional conditions requiring special processing, often changing the normal flow of program execution. The main keywords for this process are try, throw, and catch.

Key Points:

Exception Class

The base class for handling exceptions is the Exception class. This class contains information about the error such as the error text, source file, line number, and date.

#include <iostream>
using namespace std;

class Exception {
protected:
    string text;
    string source; // file
    int line;
    string date;

public:
    Exception(string text, string source, int line, string date)
        : text(text), source(source), line(line), date(date) {}

    virtual void PrintMessage() const {
        cout << " ========= ERROR INFO ========= " << endl;
        cout << " Error Content : " << text << endl;
        cout << " Source : " << source << endl;
        cout << " Line Number : " << line << endl;
        cout << " Date : " << date << endl;
    }
};

Custom Exception Classes

We can create more specific exception types by inheriting from the base Exception class. Below are examples of two such custom exception classes, OutOfRangeException and InvalidArgumentException.

class OutOfRangeException : public Exception {
public:
    OutOfRangeException(string text, string source, int line, string date)
        : Exception(text, source, line, date) {}

    void PrintMessage() const override {
        cout << " Error type : " << "OutOfRangeException" << endl;
        Exception::PrintMessage();
    }
};

class InvalidArgumentException : public Exception {
public:
    InvalidArgumentException(string text, string source, int line, string date)
        : Exception(text, source, line, date) {}

    void PrintMessage() const override {
        cout << " Error type : " << "InvalidArgumentException" << endl;
        Exception::PrintMessage();
    }
};

Exception Handling in a Class

In a class or function, we can specify which exceptions might be thrown using the throw keyword. In the Array class below, the constructor and operator[] function throw InvalidArgumentException and OutOfRangeException respectively.

template<typename T>
class Array {
private:
    T* data;
    int size;

public:
    int GetSize() const {
        return size;
    }

    Array<T>& operator=(const Array<T>& other) = delete;
    Array(const Array<T>& other) = delete;

    Array(int size) throw(InvalidArgumentException) {
        if (size < 0 || size > 1000000) {
            throw new InvalidArgumentException("Size should be between 0 and 1000000",
                __FILE__, __LINE__, __DATE__);
        }
        this->size = size;
        data = new T[size]{};
    }

    T& operator[](int index) throw(OutOfRangeException) {
        if (index < 0 || index >= size) {
            throw new OutOfRangeException("Index should be more than 0 and less than " << size,
                __FILE__, __LINE__, __DATE__);
        }
        return data[index];
    }
};

Using the Exception Classes

In the main function, we can use a try-catch block to handle any exceptions that might be thrown. The catch block catches exceptions of type Exception*, calling the PrintMessage function to print the error details.

int main() {
    try {
        Array<int> a(-10);
    } catch (const Exception *ex) {
        ex->PrintMessage();
    }
    return 0;
}

In the above code, an InvalidArgumentException is thrown when we try to create an array with a negative size. The catch block catches this exception and calls the PrintMessage function to print the details of the error.

Reference

The content in this document is based on the original notes provided in Azerbaijani. For further details, you can refer to the original document using the following link:

Original Note - Azerbaijani Version