• 为了保证你在浏览本网站时有着更好的体验,建议使用类似Chrome、Firefox之类的浏览器~~
    • 如果你喜欢本站的内容何不Ctrl+D收藏一下呢,与大家一起分享各种编程知识~
    • 本网站研究机器学习、计算机视觉、模式识别~当然不局限于此,生命在于折腾,何不年轻时多折腾一下

C++11 之Exception and Error

C++ admin 3年前 (2015-05-30) 845次浏览 0个评论 扫描二维码

引言

在现代 C++ 中,大多数情况下报告和处理逻辑错误和运行时错误的首选方式都是使用异常。 当堆栈可能包含一些在可检测错误的函数和具有上下文来了解如何解决该错误的函数间的函数调用时,更是如此。 异常提供正式且定义完善的代码检测错误方法,以在调用堆栈上向上传递信息。

程序错误通常分为两类:第一类为由编程错误导致的逻辑错误,例如,“索引超出范围”错误。第二类为超出程序员控制的运行时错误,例如“网络服务不可用”错误。 在 C 风格编程和 COM 中,通过返回代表错误代码或特殊函数状态代码的值或者通过设置调用方可在每次调用函数后检索以确定是否已报告错误的全局变量管理错误报告。 例如,COM 编程使用 HRESULT 返回值来将错误传递给调用方,而 Win32 API 使用 GetLastError 函数来检索由调用堆栈报告的上一个错误。 在这两种情况下,由调用方识别代码并相应地作出回应。 如果调用方未显式处理错误代码,则程序可能在不发出任何警告的情况下崩溃,或者继续使用错误数据执行并产生错误结果。

现代 C++ 更趋向于使用异常的原因如下:

– 异常强制调用代码识别错误条件并对其进行处理。 未经处理的异常会中止程序执行。

– 异常跳转到能够处理错误的调用堆栈的点。 中间函数可导致异常传播。 它们不必与其他层相协调。

– 在引发异常后,异常堆栈展开结构基于显式定义的规则销毁处于范围内的所有对象。

– 异常将介于检测错误和处理错误之间的代码完全分离。

异常捕捉

异常捕捉的方式主要是通过[try,catch]完成,语法格式如下:

ry{
//function operation
}
catch(exception resource)
{
//handle exception
}

异常处理

异常处理的方式有两种:

– 用户自定义(User-defined)

– C++11 提供异常处理

用户自定义

// HandleExcepetion.cpp : 定义控制台应用程序的入口点。

#include
using namespace std;
const int num = 5;
class MyClass
{
public:
MyClass();
MyClass(int size = num);
int & operator[](int off);
const int & operator[](int off)const;
int Getsize()const{ return size; };
class Wrong{};//定义错误异常
class offset{ // 偏移异常类的定义
public:
offset(int Size) :size(Size){};
~offset(){};
virtual int get(){ return size; };
virtual void show(){ cout << "抛出 offset 异常" << endl;
cout << "异常的下标为" << size << "出错" << endl;
}
protected:
int size;
};
class Big :public offset//偏移较大
{
public:
Big(int Size) :offset(Size){};
virtual void show()
{
cout << "抛出 Big 异常" << endl;
cout << "异常的下标为" << offset::size << "出错" << endl;
}
};
class Nav :public offset//无偏移
{
public:
Nav(int size) :offset(size){};
virtual void show()
{
cout << "抛出 Nav 异常" << endl;
cout << "异常的下标为" < }
};
class small//偏移很小
{
public:
small(int Size) :size(Size){}
virtual int get(){ return size; };
virtual void show(){
cout << "抛出 small 异常" << endl;
cout << "异常的下标" << size << "出错"<<endl;
}
~small(){};
protected:
int size;
private:
};
class zero : public small//偏移为 0
{
public:
zero(int size) :small(size){}
virtual void show()
{
cout << "抛出 zero 异常" << endl;
cout << "异常的下标" << small::size << "出错" << endl;
}

};
~MyClass(){ delete[]p; }

private:
int size;
int *p;
};

MyClass::MyClass(int size /* = num */) :size(size)
{
cout << "Myclass Constuctor operation" << endl;
if (size==0)
{
throw small(size);
}
if (size<10) { throw small(size); } if (size>1000)
{
throw Big(size);
}
if (size<1)
{
throw Nav(size);
}
p = new int[size];
for (int i = 0; i++;i<size)
{
p[i] = 0;
}
}
int & MyClass:: operator[](int off)
{
if (off<0&&off<Getsize())
{
return p[off];
}
throw Wrong();
return p[0];
}
const int & MyClass::operator[](int off)const
{
if (off {
return p[off];
}
throw Wrong();
return p[0];
}
int _tmain(int argc, _TCHAR* argv[])
{
try
{
MyClass me(0);//试图捕获偏移为 0 异常

}
catch (MyClass::small &zero)
{
zero.show();
}
catch (MyClass::Big &big)
{
big.show();
}
catch (MyClass::Nav &nav)
{
nav.show();
}

return 0;
}

解释:在上述的代码中定义了错误异常类 Wrong 和偏移异常类 offset,针对偏移异常又细分了几种情况即偏移较大 Big、便宜较小 small 等。代码对对每一个类定义了相应的虚函数、构造函数等。

系统定义

系统定义的异常类在:

`#include<stdexcept>`中包含的异常类定义如下:

#include
#include #include

using namespace std;
class MyClass
{
public:
void MyFunc(char c)
{
if(c < numeric_limits::max())
throw invalid_argument("MyFunc argument too large.");
//...
}
};

int main()
{
try
{
MyFunc(256); //cause an exception to throw
}

catch(invalid_argument& e)
{
cerr << e.what() << endl;
return -1;
}
//...
return 0;
}

结论

异常和断言是检测程序中运行时错误的两个不同的机制。 如果您的所有代码都是正确的,那么对于开发中绝不应为 true 的条件,请使用断言进行测试。 无法使用异常来处理此类错误,因为错误表明需要确认代码的某部分,但不代表在运行时程序需从某状况中恢复。 断言停止执行该语句,以便您可以检查调试器中的程序状态;异常继续从第一个正确 catch 处理程序开始执行。 使用异常检查运行时可能会出现的错误条件(即使您的代码是正确的),例如“未找到文件”或“在内存不足”。您可能希望从这些情况恢复,即使恢复仅向日志输出一条消息就结束程序。 请始终使用异常检查公共函数的参数。 即使您的功能没有错误,但也可能不能完全控制用户传递给它的参数。

 患病未患病合计
吸烟37183220
不吸烟21274295
合计58457515


Deeplearn, 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明C++11 之 Exception and Error
喜欢 (0)
admin
关于作者:

您必须 登录 才能发表评论!