// 异常的多态
#include <iostream>
#include <cstring>
#include <cstdlib>

using namespace std;

class Exception
{
private:
    string msg;

public:
    Exception()
    {
        this->msg = "";
        cout << this << " :   Exception()" << endl;
    }
    Exception(const string &msg)
    {
        this->msg = msg;
        cout << this << " :   Exception(const string &)" << endl;
    }
    Exception(const Exception &other)
    {
        this->msg = other.msg;
        cout << this << " :   Exception(const Exception &)" << endl;
    }
    ~Exception() { cout << this << " :   ~Exception()" << endl; }

public:
    string &getMsg() // const 表示该成员函数不会修改成员变量
    {
        return this->msg;
    }
};

class ZeroDivisionException : public Exception
{
public:
    ZeroDivisionException() {}
    ZeroDivisionException(const string &msg) : Exception(msg) {}
};

class OutOfRangeException : public Exception
{
public:
    OutOfRangeException() {}
    OutOfRangeException(const string &msg) : Exception(msg) {}
};

int main(int argc, char const *argv[])
{
    int n = atoi(argv[1]);
    try
    {
        if (n == 0)
            // 抛出子类的异常对象
            throw ZeroDivisionException("除数为不能 0");
        else if (n >= 20)
            throw OutOfRangeException("范围越界 20");
        else if (n == 10)
            throw Exception("n 不能为 10");
        else
            cout << "n = " << n << endl;
    }
    catch (ZeroDivisionException &error) // 接子类引用
    {
        cout << "精准捕获到子类异常: " << error.getMsg() << endl;
    }
    catch (Exception &e) // 接父类引用（要写到子类异常的后面）
    {
        cout << "捕获异常: " << e.getMsg() << endl;
    }
    catch (...) // 捕获所有异常
    {
        cout << "捕获所有异常" << endl;
    }

    return 0;
}