- 错误处理技术
1.终止程序(段错误)
2.返回错误码
3.返回合法值
4.调用一个预先设置的出现错误时调的函数(回调函数) 异常处理
-当一个函数发现自己无法处理的错误时抛出异常,让函数的调用者直接或间接的处理这个问题。异常的抛出和捕获
- 异常是通过抛出对象而引发的,对象的类型决定了应该激活哪个处理代码。
- 处理代码是与该对象类型匹配且离抛出异常位置最近的哪个
- 抛出异常后会释放局部存储对象,所处被抛出的对象叶欢给操作系统了,throw会初始化一个抛出特殊的异常对象副本(匿名对象),异常对象由编译管理,对象传给对应的catch处理后撤销。- 栈展开
- 抛出异常的时候,暂停当前函数的执行,开始查找对应的匹配catch。
- 首先在throw本身是否在团员块内部,如果是查找catch,如果有匹配的,就处理;如果没有匹配的,则退出当前函数栈,继续在调用函数的栈中查找;如果到main函数的栈依旧没有找到匹配的,就终止程序。 - 异常捕获的匹配规则
-异常对象类型与catch的类型必须完全匹配
例外:
1.从非const对象到const对象。
2.从派生类型到基类类型的转换。
3.数组转换为指向数组的指针,函数转换为指向函数的指针。
#include <iostream>
#include <string>
using namespace std;
class Exception
{
public :
Exception(int errId, const char * errMsg)
: _errId(errId )
, _errMsg(errMsg )
{}
void What () const
{
cout<<"errId:" <<_errId<< endl;
cout<<"errMsg:" <<_errMsg<< endl;
}
private :
int _errId ; // 错误码
string _errMsg ; // 错误消息
};
void Func1 (bool isThrow)
{
// ...
if (isThrow )
{
throw Exception (1, "抛出 Excepton对象" );
}
// ...
printf("Func1(%d)\n" , isThrow);
}
void Func2 (bool isThrowString, bool isThrowInt)
{
// ...
if (isThrowString )
{
throw string ("抛出 string对象" );
}
// ...
if(isThrowInt )
{
throw 7;
}
printf("Func2(%d, %d)\n" , isThrowString, isThrowInt );
}
void Func ()
{
try
{
Func1(false );
Func2(true , true);
}
catch(const string& errMsg)
{
cout<<"Catch string Object:" <<errMsg<< endl;
}
catch(int errId)
{
cout<<"Catch int Object:" <<errId<< endl;
}
catch(const Exception& e)
{
e.What ();
}
catch(...)
{
cout<<" 未知异常"<< endl;
}
printf ("Func()\n");
}
int main()
{
Func();
return 0;
}
运行结果如下:
- 异常的重新抛出
有可能单个catch不能完全处理一个异常,在进行一些校正处理后,希望再交给更外层的调用链函数来处理,catch则可以通过重新将异常传递给上层的函数来进行处理。
#include <iostream>
#include <string>
using namespace std;
class Exception
{
public :
Exception(int errId = 0, const char * errMsg = "" )
: _errId(errId )
, _errMsg(errMsg )
{}
void What () const
{
cout<<"errId:" <<_errId<< endl;
cout<<"errMsg:" <<_errMsg<< endl;
}
private :
int _errId ; // 错误码
string _errMsg ; // 错误消息
};
void Func1 ()
{
throw string ("Throw Func1 string");
}
void Func2 ()
{
try
{
Func1();
}
catch(string & errMsg)
{
cout<<errMsg <<endl;
Exception e (1, "Rethorw Exception");
throw e ;
// throw;
// throw errMsg;
}
}
void Func3 ()
{
try
{
Func2();
}
catch (Exception & e)
{
e.What ();
}
}
int main()
{
Func3();
return 0;
}
运行结果如下:
- 异常 构造函数&析构函数
- 构造函数完成对象的构造和初始化,要保证不在构造函数中抛出异常,否则可能导致对象不完整或没有完全初始化
- 析构函数 主要完成资源的清理,保证不在析构函数中抛出异常,否则导致资源泄漏(内存泄漏,句柄未关闭等)。