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()在每个派生类中重定义, 并发出相应的错误信息
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报告程序运行时的错误, 只有在运行时才能检测到
runtime_error报告程序运行时的错误, 只有在运行时才能检测到
3 逻辑异常类
派生类logic_error又有自己的派生类. 其中派生类的名称及其功能如下:
domain_error: 报告违反了前置条件的错误
invalid_error: 指出函数收到一个无效参数(派生自domian_error类)
length_error: 指出长度超过操作对象所允许的最大长度
out_of_error: 报告参数越界
派生类logic_error又有自己的派生类. 其中派生类的名称及其功能如下:
domain_error: 报告违反了前置条件的错误
invalid_error: 指出函数收到一个无效参数(派生自domian_error类)
length_error: 指出长度超过操作对象所允许的最大长度
out_of_error: 报告参数越界
4 运行异常类
派生类runtime_error又有自己的派生类. 其中派生类的名称及其功能如下:
range_error: 报告计算时发生区间错误
overflow_error: 报告发生运算上溢错误
underflow_error: 报告发生下溢错误
派生类runtime_error又有自己的派生类. 其中派生类的名称及其功能如下:
range_error: 报告计算时发生区间错误
overflow_error: 报告发生运算上溢错误
underflow_error: 报告发生下溢错误
此外还有一些运行异常类, 如bad_alloc类报告存储分配错误
异常基础类定义在头文件<exception>中, bad_alloc类定义于<new>中, 其他异常类定义在<stdexcep>中
C++标准库的这些异常类没有被全部显式使用, 因为C++标准库很少发生异常
C++标准库的这些异常类没有被全部显式使用, 因为C++标准库很少发生异常
自定义异常类
throw语句能够抛出任意类型的一个值, 在开发中, 程序员可以向标准库一样定义一些异常类, 它们的对象专门负责容纳抛给catch块的
信息
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; } }
路漫漫其修远兮,吾将上下而求索。