C++面向对象入门(四十九)异常类和自定义异常类

C++标准库定义了异常类层次:
1 exception类: 所有C++异常的基类, 定义在库的头文件<exception>中, 其接口定义如下:
class exception
{
public:
 exception() throw();
 exception(const exception &rhs) throw();
 exception& operator=(const exception& rhs) throw();
 virtual ~exception() throw();
 virtual const char* what() const throw();
};
其中what()在每个派生类中重定义, 并发出相应的错误信息
2 logic_error类和runtime_error类: exception类的直接派生异常类. 其中logic_error报告程序的逻辑错误, 可在程序执行前被检到,
runtime_error报告程序运行时的错误, 只有在运行时才能检测到
3 逻辑异常类
派生类logic_error又有自己的派生类. 其中派生类的名称及其功能如下:
domain_error: 报告违反了前置条件的错误
invalid_error: 指出函数收到一个无效参数(派生自domian_error类)
length_error: 指出长度超过操作对象所允许的最大长度
out_of_error: 报告参数越界
4 运行异常类
派生类runtime_error又有自己的派生类. 其中派生类的名称及其功能如下:
range_error: 报告计算时发生区间错误
overflow_error: 报告发生运算上溢错误
underflow_error: 报告发生下溢错误
此外还有一些运行异常类, 如bad_alloc类报告存储分配错误
异常基础类定义在头文件<exception>中, bad_alloc类定义于<new>中, 其他异常类定义在<stdexcep>中
C++标准库的这些异常类没有被全部显式使用, 因为C++标准库很少发生异常
自定义异常类
throw语句能够抛出任意类型的一个值, 在开发中, 程序员可以向标准库一样定义一些异常类, 它们的对象专门负责容纳抛给catch块的
信息
为什么要使用自定义异常类?
能够分别用不同的类型来标识每一种可能出现的异常情况
 
代码示例:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
/*
C++标准库定义了异常类层次:

1 exception类: 所有C++异常的基类, 定义在库的头文件<exception>中, 其接口定义如下:
class exception
{
public:
    exception() throw();
    exception(const exception &rhs) throw();
    exception& operator=(const exception& rhs) throw();
    virtual ~exception() throw();
    virtual const char* what() const throw();
};
其中what()在每个派生类中重定义, 并发出相应的错误信息

2 logic_error类和runtime_error类: exception类的直接派生异常类. 其中logic_error报告程序的逻辑错误, 可在程序执行前被检到,
runtime_error报告程序运行时的错误, 只有在运行时才能检测到

3 逻辑异常类
派生类logic_error又有自己的派生类. 其中派生类的名称及其功能如下:
domain_error: 报告违反了前置条件的错误
invalid_error: 指出函数收到一个无效参数(派生自domian_error类)
length_error: 指出长度超过操作对象所允许的最大长度
out_of_error: 报告参数越界

4 运行异常类
派生类runtime_error又有自己的派生类. 其中派生类的名称及其功能如下:
range_error: 报告计算时发生区间错误
overflow_error: 报告发生运算上溢错误
underflow_error: 报告发生下溢错误

此外还有一些运行异常类, 如bad_alloc类报告存储分配错误

异常基础类定义在头文件<exception>中, bad_alloc类定义于<new>中, 其他异常类定义在<stdexcep>中
C++标准库的这些异常类没有被全部显式使用, 因为C++标准库很少发生异常

自定义异常类
throw语句能够抛出任意类型的一个值, 在开发中, 程序员可以向标准库一样定义一些异常类, 它们的对象专门负责容纳抛给catch块的
信息

为什么要使用自定义异常类?
能够分别用不同的类型来标识每一种可能出现的异常情况
*/

class Negativenumber
{
private:
    string message;
public:
    Negativenumber();
    Negativenumber(string s);
    string getMessage();
};

class DivideByZero{};

void test1EHSL() throw (Negativenumber, DivideByZero);

void handler1EHSL();

ofstream log_no68("log_no68.txt", ios::app);

int main()
{
    handler1EHSL();
    log_no68 << "End of program." << endl;
    log_no68.close();
    return 0;
}

Negativenumber::Negativenumber()
{
}

Negativenumber::Negativenumber(string s): message(s)
{
}

string Negativenumber::getMessage()
{
    return message;
}

void test1EHSL() throw(Negativenumber, DivideByZero)
{
    double totalMoney, averPrice;
    int bookAmount;
    cout << "Enter total money of your books:" << endl;
    cin >> totalMoney;
    if (totalMoney < 0)
    {
        throw Negativenumber("total money is less than 0");
    }

    cout << "Enter amount of books:" << endl;
    cin >> bookAmount;
    if (bookAmount < 0)
    {
        throw Negativenumber("amount of books is less than 0");
    }
    if (bookAmount > 0 && totalMoney > 0)
    {
        averPrice = totalMoney / bookAmount;
    }
    else if (bookAmount == 0)
    {
        throw DivideByZero();
    }

    if (bookAmount > 0 && totalMoney > 0)
        log_no68 << "Average price all of books is " << averPrice << endl;
    else
        log_no68 << "your input is error!" << endl;
}

void handler1EHSL()
{
    try
    {
        test1EHSL();
    }
    catch (Negativenumber e)
    {
        string message= e.getMessage();
        log_no68 << message << endl;
    }
    catch (DivideByZero)
    {
        log_no68 << "The amount of books is zero, error!" << endl;
    }
}

 

posted @ 2020-09-09 20:50  DNoSay  阅读(472)  评论(0编辑  收藏  举报