异常处理
异常时程序在执行期间产生的问题。C++异常是指在程序运行时发生的特殊情况,比如尝试除以零的操作。
异常提供了一种转移程序控制权的方式。C++异常处理涉及到三个关键字:try、catch、throw
l throw:当问题出现时,程序回抛出一个异常。这是通过使用throw关键字来完成。
l catch:当你想处理问题的地方,通过异常处理程序捕获异常。catch关键字用于异常捕捉。
l try:try块中的代码标识将被激活的特定异常。它后面通常跟着一个或多个catch块。
如果有一个块抛出一个异常,捕获异常的方法会使用try和catch关键字。try中放置可能抛出异常的代码。try块中的代码被称为保护代码。使用try/catch语句的语法如下:
try { //保护代码 } catch(ExceptionName e1) { //catch块 } catch(ExceptionName e2) { //catch块 } catch(ExceptionName eN) { //catch块 }
如果try块在不同情境下会抛出不同的异常,这个时候就可以尝试罗列出多个catch语句,用于捕获不同的异常。
抛出异常
可以使用throw语句在代码块中的任何地方抛出异常,throw语句的操作数可以时任意的表达式,表达式的结果的类型决定了抛出的异常的类型。
实例:
/*** try.cpp ***/ #include<iostream> using namespace std; double division(int a,int b) { if(b == 0) { throw "Division by zero condition"; } return a/b; } int main() { int x = 50; int y = 0; double z = 0; try { z = division(x,y); cout << z << endl; } catch(const char *msg) { cerr << msg << endl; } return 0; }
由于我们抛出一个类型为const char* 的异常,因此,当捕获该异常时,我们必须在catch块中使用const char*。
运行结果:
exbot@ubuntu:~/wangqinghe/C++/20190813$ g++ try.cpp -o try
exbot@ubuntu:~/wangqinghe/C++/20190813$ ./try
Division by zero condition
C++标准异常
C++提供了一系列标准的异常,定义在<expection>中,我们可以在程序中使用这些标准的异常,他们是以父子类层次结构组织起来的。
下图是对上层结构中出现的每个异常的说明:
定义新的异常
可以通过继承和重载exception来定义新的异常。
/*** exception.cpp ***/ #include<iostream> #include<exception> using namespace std; struct MyException:public exception { const char* what() const throw() { return "C++ Exception"; } }; int main() { try { throw MyException(); } catch(MyException& e) { cout << "MyException caught" << endl; cout << e.what() << endl; } catch(exception& e) { // } }
运行结果:
exbot@ubuntu:~/wangqinghe/C++/20190813$ ./exception
MyException caught
C++ Exception
在这里,what()是异常类提供的一个公共方法,它已被所有子异常类重载。这将返回异常产生的原因。
const throw()不是函数,这个东西叫异常规格说明,表示what函数可以抛出异常的类型,类型说明放在()里,这里面没有类型,就是声明这个函数不抛出异常,通常这个函数不写后面的就表示函数可以抛出任何类型的异常。
异常规格说明
- 异常规格说明的目的就是为了让函数使用者知道该函数可能从哪里抛出的异常有哪些。可以在函数的声明中列出这个函数可能抛出的所有异常类型。例如:
void fun() throw(A,B,C,D)
- 如无异常接口说明,则此函数可以抛掷任何类型的异常。
- 不抛掷任何类型异常的函数声明如下:
/*** exception.cpp ***/ #include<iostream> #include<exception> using namespace std; class MyException { public: MyException(const char *message):message_(message) { cout << "MyException ..." << endl; } MyException(const MyException &other):message_(other.message_) { cout << "copy MyException ... " << endl; } virtual ~MyException() { cout << "~MyException ..." << endl; } const char* what() const { return message_.c_str(); } private: string message_; }; class MyExceptionD : public MyException { public: MyExceptionD(const char*message):MyException(message) { cout << "MyExceptionD ..." << endl; } MyExceptionD(const MyExceptionD &other):MyException(other) { cout << "Copy MyExceptionD ..." << endl; } ~MyExceptionD() { cout << "~MyException..." << endl; } }; void fun(int n) throw(int ,MyException,MyExceptionD) { if(1 == n) { throw 1; } else if(2 == n) { throw MyException("test Exception"); } else if(3 == n) { throw MyException("test ExceptionD"); } } void fun2() throw() { } int main() { try { fun(2); } catch(int n) { cout << "catch int ..." << endl; cout << "n = " << n << endl; } catch(MyExceptionD &e) { cout << "catch MyExceptionD ..." << endl; cout << e.what() << endl; } catch(MyException &e) { cout << "catch MyException ..." << endl; cout << e.what() << endl; } return 0; }
运行结果:
exbot@ubuntu:~/wangqinghe/C++/20190814$ g++ exception.cpp -o exception
exbot@ubuntu:~/wangqinghe/C++/20190814$ ./exception
MyException ...
catch MyException ...
test Exception
~MyException ...
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
2018-08-14 1026 Table Tennis (30)