C++ try catch异常处理语句的用法(附带实例)
异常信号抛出后,一旦被异常处理器接收到就会被销毁。C++ 程序中,异常处理器通常紧跟在 try 语句后,处理方法由关键字 catch 引导。
下面通过 try…catch 语句捕获一个异常,程序代码如下:
通过 throw 关键字抛出异常时需指定这两个参数。注意,throw 语句可以直接写在 try 语句块的内部,也可以写在函数或类方法的内部,再将函数或方法写在 try 语句块内部。
捕获异常时,异常处理器还可以成组出现,根据捕获到的不同信息进行不同的处理。例如:
有时无法在列出的异常处理中包含所有可能发生的异常类型,C++ 提供了可以处理未知类型异常的方法,就是在 catch 后面的括号内添加“…”。程序代码如下:
有时需要重新抛出刚接收到的异常,尤其在程序无法得到相关异常信息而用省略号表示时。重新抛出异常可通过不带参数的 throw 语句完成。例如:
异常匹配并不要求异常与异常处理器进行完美匹配,一个对象或一个派生类对象的引用将与基类处理器进行匹配。若抛出的是类对象的指针,则会匹配相应的对象类型,但不会自动转换成其他对象的类型。例如:
下面看下基类处理器如何捕获派生类的异常:
下面通过 try…catch 语句捕获一个异常,程序代码如下:
#include<iostream>
#include <string>
using namespace std;
class CCustomError // 定义异常类 CCustomError
{
private:
int m_ErrorID; // m_ErrorID 表示异常 ID
char m_Error[255]; // m_Error 表示异常信息
public:
CCustomError() // 构造函数
{
m_ErrorID = 1;
strcpy(m_Error,"出现异常!");
}
int GetErrorID() // GetErrorID() 方法,用于获取异常 ID
{
return m_ErrorID;
}
char *GetError() // 重载 GetErrorID() 方法,用于获取异常信息
{
return m_Error;
}
};
int main(int argc, char *argv)
{
try // 检测异常
{
throw (new CCustomError()); // 抛出异常
}
catch(CCustomError *error) // 捕获异常
{
// 输出异常信息
cout << "异常 ID: " << error->GetErrorID() << endl;
cout << "异常信息:" << error->GetError() << endl;
}
return 0;
}
程序中定义了一个异常类,该类包含两个内容:
- 一个是异常 ID,即异常信息的编号;
- 另一个是异常信息,即异常的说明文本。
通过 throw 关键字抛出异常时需指定这两个参数。注意,throw 语句可以直接写在 try 语句块的内部,也可以写在函数或类方法的内部,再将函数或方法写在 try 语句块内部。
捕获异常时,异常处理器还可以成组出现,根据捕获到的不同信息进行不同的处理。例如:
int main(int argc, char *argv)
{
try
{
throw "字符串异常!";
// throw (new CCustomError());
// 抛出异常
}
catch(CCustomError *error) // 捕获异常1
{
cout << "异常 ID:" << error->GetErrorID() << endl;
cout << "异常信息:" << error->GetError() << endl;
}
catch(char *error) // 捕获异常2
{
cout << "异常信息:" << error << endl;
}
return 0;
}
有时无法在列出的异常处理中包含所有可能发生的异常类型,C++ 提供了可以处理未知类型异常的方法,就是在 catch 后面的括号内添加“…”。程序代码如下:
int main(int argc, char *argv)
{
try
{
throw "字符串异常!"; // 抛出字符串异常
// throw (new CCustomError()); // 抛出 CCustomError 类异常
}
catch(CCustomError *error) // 捕获异常1
{
cout << "异常ID:" << error->GetErrorID() << endl;
cout << "异常信息:" << error->GetError() << endl;
}
catch(char *error) // 捕获异常2
{
cout << "异常信息:" << error << endl;
}
catch(...) // 捕获未知异常
{
cout << "未知异常信息!" << endl;
}
return 0;
}
有时需要重新抛出刚接收到的异常,尤其在程序无法得到相关异常信息而用省略号表示时。重新抛出异常可通过不带参数的 throw 语句完成。例如:
catch (...)
{
cout << "未知异常!" << endl;
throw;
}
如果 catch 语句忽略了某个异常,该异常将进入更高层级的异常处理器。每个异常抛出的对象都会被保留,因此更高层的异常处理器可抛出来自这个对象的所有信息。异常匹配
当程序中有异常抛出时,异常处理系统根据异常处理器的顺序找到最近的异常处理块,并不会搜索更多的异常处理块。异常匹配并不要求异常与异常处理器进行完美匹配,一个对象或一个派生类对象的引用将与基类处理器进行匹配。若抛出的是类对象的指针,则会匹配相应的对象类型,但不会自动转换成其他对象的类型。例如:
class CExcept1 {};
class CExcept2
{
public:
CExcept2(CExcept1& e) {}
};
int main(int argc, char *argv)
{
try
{
throw CExcept1(); // 抛出异常
}
catch (CExcept2) // 捕获异常1
{
printf("进入 CExcept2 异常处理器!\n");
}
catch(CExcept1) // 捕获异常2
{
printf("进入 CExcept1 异常处理器!\n");
}
return 0;
}
程序中,第一个异常处理器使用构造函数进行转换,将 CExcept1 转换为 CExcept2 对象,但实际上系统在异常处理期间并不执行这样的转换,而是在 CExcept1 处终止。下面看下基类处理器如何捕获派生类的异常:
#include<iostream>
using namespace std;
class CExcept
{
public:
virtual char *GetError() { return "基类处理器"; }
};
class CDerive : public CExcept
{
public:
char *GetError() { return "派生类处理器"; }
};
int main(int argc, char *argv)
{
try
{
// 抛出异常
throw CDerive();
}
catch(CExcept) // 捕获异常
{
cout << "进入基类处理器\n";
}
catch(CDerive) // 捕获异常
{
cout << "进入派生类处理器\n";
}
return 0;
}
程序中,虽然抛出的异常是 CDerive 类,但异常处理器的第一个是 CExcept 类,该类是 CDerive 类的基类,因此将进入此异常处理器内部。为了正确进入指定的异常处理器,在对异常处理器进行排列时应将派生类排在前面,而将基类排在后面。
ICP备案:
公安联网备案: