C++异常机制概述
作者:melonstreet 整理:cpp开发者 出处:https://www.cnblogs.com/QG-whz/
以下是正文
C++异常机制概述
一个最简单的 try...catch... 的例子如下所示。我们有个程序用来记班级学生考试成绩,考试成绩分数的范围在 0-100 之间,不在此范围内视为数据异常:
int main()
{
int score=0;
while (cin >> score)
{
try
{
if (score > 100 || score < 0)
{
throw score;
}
//将分数写入文件或进行其他操作
}
catch (int score)
{
cerr << "你输入的分数数值有问题,请重新输入!";
continue;
}
}
}
throw 表达式;
//示例代码:throw包含在外层函数的try块中
void registerScore(int score)
{
if (score > 100 || score < 0)
throw score; //throw语句被包含在外层main的try语句块中
//将分数写入文件或进行其他操作
}
int main()
{
int score=0;
while (cin >> score)
{
try
{
registerScore(score);
}
catch (int score)
{
cerr << "你输入的分数数值有问题,请重新输入!";
continue;
}
}
}
异常对象
标准异常类 | 描述 | 头文件 |
---|---|---|
exception | 最通用的异常类,只报告异常的发生而不提供任何额外的信息 | exception |
runtime_error | 只有在运行时才能检测出的错误 | stdexcept |
rang_error | 运行时错误:产生了超出有意义值域范围的结果 | stdexcept |
overflow_error | 运行时错误:计算上溢 | stdexcept |
underflow_error | 运行时错误:计算下溢 | stdexcept |
logic_error | 程序逻辑错误 | stdexcept |
domain_error | 逻辑错误:参数对应的结果值不存在 | stdexcept |
invalid_argument | 逻辑错误:无效参数 | stdexcept |
length_error | 逻辑错误:试图创建一个超出该类型最大长度的对象 | stdexcept |
out_of_range | 逻辑错误:使用一个超出有效范围的值 | stdexcept |
bad_alloc | 内存动态分配错误 | new |
bad_cast | dynamic_cast类型转换出错 | type_info |
catch 关键字
允许从非常量到常量的类型转换。
允许派生类到基类的类型转换。
数组被转换成指向数组(元素)类型的指针。
函数被转换成指向函数类型的指针。
catch(type x)
{
//做了一部分处理
throw;
}
栈展开、RAII
//一个没有任何意义的类
class A
{
public:
A() :a(0){ cout << "A默认构造函数" << endl; }
A(const A& rsh){ cout << "A复制构造函数" << endl; }
~A(){ cout << "A析构函数" << endl; }
private:
int a;
};
int main()
{
try
{
A a ;
throw a;
}
catch (A a)
{
;
}
return 0;
}
程序将输出:
int main()
{
try
{
A * a= new A;
throw *a;
}
catch (A a)
{
;
}
getchar();
return 0;
}
程序运行结果:
RAII机制有助于解决这个问题,RAII(Resource acquisition is initialization,资源获取即初始化)。它的思想是以对象管理资源。为了更为方便、鲁棒地释放已获取的资源,避免资源死锁,一个办法是把资源数据用对象封装起来。程序发生异常,执行栈展开时,封装了资源的对象会被自动调用其析构函数以释放资源。C++ 中的智能指针便符合RAII。关于这个问题详细可以看《Effective C++》条款13.
C++ 类构造函数初始化列表的异常机制,称为 function-try block。一般形式为:
myClass::myClass(type1 pa1)
try: _myClass_val (初始化值)
{
/*构造函数的函数体 */
}
catch ( exception& err )
{
/* 构造函数的异常处理部分 */
};
若析构函数抛出异常,调用 std::abort() 来终止程序。
在析构函数中 catch 捕获异常并作处理。
noexcept修饰符与noexcept操作符
void func() throw(int ,double ) {...}
void func() throw(){...}
这是 throw 作为函数异常说明,前者表示 func()这个函数可能会抛出 int 或 double 类型的异常,后者表示 func() 函数不会抛出异常。事实上前者很少被使用,在 C++11 这种做法已经被摒弃,而后者则被 C++11 的 noexcept 异常声明所代替:
void func() noexcept {...}
//等价于void func() throw(){...}
void func() noexcept(常量表达式);
关于C++异常机制,欢迎在评论中和我探讨。觉得文章不错,请点赞和在看支持我继续分享好文。谢谢!
评论