C++标准提供了一组标准异常类,这些类以基类exception开始,标准程序库抛出的所有异常,都派生与该基类,这些类构成如图所示的异常类的派生继承关系。该继承类提供一个成员函数what()
,用于返回错误信息(返回类型为const char*
)。在exception类中,what()
函数的声明如下:
virtual const char* what() const throw();
该函数可以在派生类中重新定义
下表中列出了各个具体异常类的含义及定义它们的头文件。runtime_error
和logic_error
是一些具体的异常类的基类,它们分别表示两大异常类。logic_error
表示那些可以在程序中被预先检测到的异常,也就是说如果小心地编写程序,这类异常能够避免;而runtime_error
则表示那些难以被预先检测的异常。
习惯:一些编程语言规定只能抛掷某个类的派生类(例如 Java 中允许抛掷的类必须派生自 exception 类),C++ 虽然没有这项强制的要求,但仍然可以这样实践。例如,在程序中可以使得所有抛出的异常皆派生自 exception(或者直接抛出标准程序库提供的异常类型,或者从标准程序库提供的异常类派生出新的类),这样会带来很多方便。
logic_error
和 runtime_error
两个类及其派生类,都有一个接收const string &
型参数的构造函数。在构造异常对象时需要将具体的错误信息传递给该参数,如果调用该对象的 what()
函数,就可以得到构造时提供的错误信息。
自己写了个简单的例子:
#include <iostream>
#include<stdexcept>
using namespace std;
double division(int a, int b)throw(invalid_argument)
{
if (b == 0)
{
throw invalid_argument("Division by zero condition!");//异常类invalid_argument有一个接收const string&型参数的构造函数
}
return (a / b);
}
int main()
{
int x = 50;
int y = 0;
double z = 0;
try {
z = division(x, y);
cout << z << endl;//上一句在执行中如果没有抛出异常才会执行当前这句
}
catch (const exception&obj) {//抛出的异常是invalid_argument类型的,因此接收异常的时候也要是invalid_argument类型(或其基类类型)
cout << obj.what() << endl;
}
catch (...) {
cout << "未知异常" << endl;
}
system("pause");
return 0;
}
例2:依照C++标准实现自定义异常类myException
涉及到的有(1)重写基类的what()函数,返回错误信息;(2)允许division函数抛出myException类型的异常。代码如下:
#include <iostream>
#include<stdexcept>
using namespace std;
class myException :public exception {
public:
const char* what()const throw() {//派生类对基类虚函数进行重写
cout << "Derived virtual what()" << endl;
return "Division by zero condition!";
}
};
double division(int a, int b)throw(myException)
{
if (b == 0)
{
throw myException();//抛出myException类的对象
}
return (a / b);
}
int main()
{
int x = 50;
int y = 0;
double z = 0;
try {
z = division(x, y);
cout << z << endl;
}
catch (const exception&obj) {//catch (const myException&obj)也可以,不解释了,easy
cout << obj.what() << endl;
}
catch (...) {
cout << "未知异常" << endl;
}
system("pause");
return 0;
}