C++--第26课 - 异常处理 - 下

第26课 - 异常处理 - 下

1. 问题一

有时在工程中关心是否产生了异常,而不关心具体的异常类型,C++语言中可以做到吗?

C++中的catch语句可以使用...捕获所有的异常。

#include <cstdlib>

#include <iostream>

using namespace std;

int test(int i)

{

if( i == 1 )

{

throw "p";

}

if( i == 2 )

{

throw 0.5;

}

if( i == 3 )

{

throw 3;

}

if( i == 4 )

{

throw ‘c‘;

}

return i;

}

int main(int argc, char *argv[])

{

for(int i=0; i<10; i++)

{

try

{

cout<<test(i)<<endl;

}

catch(char e)  //只能放在catch之前,否则成了死代码

{

cout<<"Exception: "<<e<<endl;

}

catch(...)

{

cout<<"Exception Occur"<<endl;

}

}

cout << "Press the enter key to continue ...";

cin.get();

return EXIT_SUCCESS;

}

运行结果:

0

Exceptin Occur

Exceptin Occur

Exceptin Occur

Exceptin:c

5

6

7

8

9

catch(...)可以捕获所有异常但却无法得到异常信息。

catch(...)一般作为最后一个异常处理块出现。

看见代码中的catch就要意识到这里在处理异常情况,而异常是在对应的try中产生的。

2. 问题二

在catch语句块中仍然可以抛出异常

#include <cstdlib>

#include <iostream>

using namespace std;

int test(int i)

{

if( (6 <= i) && (i <= 9) )

{

throw i;

}

return i;

}

int main(int argc, char *argv[])

{

try

{

for(int i=0; i<10; i++)

{

try

{

cout<<test(i)<<endl;

}

catch(int e)

{

cout<<"Exception: "<<e<<endl;

throw e;   //有异常,终止了for循环

}

}

}

catch(int e)

{

cout<<"Catch: "<<e<<endl;

}

cout << "Press the enter key to continue ...";

cin.get();

return EXIT_SUCCESS;

}

运行结果:

0

1

2

3

4

5

Exception:6

Catch:6

3. 问题三

在catch(...)语句块中,可以铜鼓不带参数的throw语句抛出捕获的异常。

#include <cstdlib>

#include <iostream>

using namespace std;

int test(int i)

{

if( (6 <= i) && (i <= 9) )

{

throw i;

}

return i;

}

int main(int argc, char *argv[])

{

try

{

for(int i=0; i<10; i++)

{

try

{

cout<<test(i)<<endl;

}

catch(...)

{

cout<<"Exception Occur"<<endl;

throw;

}

}

}

catch(int e)

{

cout<<"Catch: "<<e<<endl;

}

cout << "Press the enter key to continue ...";

cin.get();

return EXIT_SUCCESS;

}

运行结果:

0

1

2

3

4

5

Exception Occur

Catch:6

不要在构造函数中抛出异常。在构造函数可能申请系统资源,而在构造函数中抛出异常会导致对象构造不完全。不完全对象的析构函数是不会被调用的,因此可能造成资源泄漏。

4. 问题4

不要在构造函数中抛出异常。在构造函数可能申请系统资源,而在构造函数中抛出异常会导致对象构造不完全。不完全对象的析构函数是不会被调用的,因此可能造成资源泄漏。语法上来说是合法的,但是会造成问题。

构造函数中的异常示例。

#include <cstdlib>

#include <iostream>

using namespace std;

class Test

{

int* p;

public:

Test()

{

cout<<"Test()"<<endl;

p = new int[5];

throw 10; /*构造函数里面抛出异常,在这里没有被处理,去上一层main函数中 */

}

~Test()

{

cout<<"~Test()"<<endl;

delete[] p;

}

};

int main(int argc, char *argv[])

{

try

{

Test t;

}

catch(int e)  //在有异常离开 类的时候,没有调用析构函数,其中的内存就泄漏了

{

cout<<"Catch: "<<e<<endl;

}

cout << "Press the enter key to continue ...";

cin.get();

return EXIT_SUCCESS;

}

运行结果:

Test()

Catch:10

5. 工程中的异常应用

在工程中会定义一系列的异常类。

通过继承,可以得到一个异常类族。

每个类代表工程中可能出现的一种异常类型。

由于对象构造与拷贝的开销,在定义catch语句块是使用引用作为参数。

在工程中可以使用标准库中的异常类

可以将标准库中的异常类作为基类派生新的异常类。

标准库中的异常都是从exception类派生的。

exception类有两个主要的分支:logic_error用于描述程序中出现的逻辑错误,如—传递无效参数;runtime_error用于描述无法预料的事件所造成的错误,如—内存耗尽,硬件错误。

标准库中的异常

logic_error和runtime_error都提供了一个参数为字符串的构造函数,这样就可以保持错误的信息。

通过what()成员函数就可以得到错误的信息。

异常的工程应用初探

#include <cstdlib>

#include <iostream>

#include <stdexcept>

using namespace std;

class divide_by_zero : public logic_error

{

public:

divide_by_zero(const char* s) : logic_error(s)

{

}

};

double Div(double a, double b)

{

if( (-0.00000001 < b) && ( b < 0.00000001) )

{

throw divide_by_zero("Divide by zero...");

}

return  a / b;

}

int main(int argc, char *argv[])

{

try

{

cout<<Div(1, 0)<<endl;

}

catch(exception& e)

{

cout<<e.what()<<endl;

}

cout << "Press the enter key to continue ...";

cin.get();

return EXIT_SUCCESS;

}

运行结果:

Divide by zero...

6. 函数级try语法

可以将函数体作为一个完整的try语句块。

int func(int i)

{

try

{

return i;

}

catch(...)

{

return -1;

}

}

等价于

int func(int i) try

{

return i;

catch(...)

{

return -1;

}

}

函数级try语法可以更好将正常逻辑代码与异常处代码分开,提高了代码的可读性与维护性。

#include <cstdlib>

#include <iostream>

#include <stdexcept>

using namespace std;

int func1(int i)

{

try

{

if( i > 0 )

{

return i;

}

else

{

throw "error";

}

}

catch(...)

{

return -1;

}

}

int func2(int i) try

{

if( i > 0 )

{

return i;

}

else

{

throw "error";

}

}

catch(...)

{

return -1;

}

int main(int argc, char *argv[])

{

for(int i=0; i<5; i++)

{

cout<<func2(i)<<endl;

}

cout << "Press the enter key to continue ...";

cin.get();

return EXIT_SUCCESS;

}

运行结果:

-1

1

2

3

4

小结:

catch(...)可以捕获所有异常。

catch(...)经常作为最后一个catch语句出现。

不要在构造函数中够抛出异常,这样可能造成资源泄露。

工程中经常以标准库中的异常类作为项目异常的基础。

函数级try语句块能够更好的提高代码的维护性。

原文地址:https://www.cnblogs.com/free-1122/p/11336318.html

时间: 2024-11-02 23:28:35

C++--第26课 - 异常处理 - 下的相关文章

第四课 文件系统(下)

====================第四课 文件系统(下)==================== 一.sync/fsync/fdatasync------------------------ 1. 大多数磁盘I/O都通过缓冲进行, 写入文件其实只是写入缓冲区,直到缓冲区满, 才将其排入写队列. 2. 延迟写降低了写操作的次数,提高了写操作的效率, 但可能导致磁盘文件与缓冲区数据不同步. 3. sync/fsync/fdatasync用于强制磁盘文件与缓冲区同步. 4. sync将所有被修改

iOS Dev (26) 初步了解下UIColor的最常用知识

作者:CSDN 大锐哥 地址:http://blog.csdn.net/prevention - 内置的颜色有啥? // Some convenience methods to create colors. These colors will be as calibrated as possible. // These colors are cached. + (UIColor *)blackColor; // 0.0 white + (UIColor *)darkGrayColor; // 0

C++--第25课 - 异常处理 - 上

第25课 - 异常处理 - 上 1. 典型问题一 所有的代码都有可能不按照预定的方式进行 double Div(double a, double b) {    return a / b;} double Add(double a, double b) {    return a + b;} double Minus(double a, double b) {    return a - b;} double Multi(double a, double b) {    return a * b

新标日中级下26课作业

63

第26课:返回值

有些命令在执行之后将会返回一定的错误值(errorlevel),可以通过errorlevel的值判断命令执行的状况.这点类似于C语言里面的exit(num),num就是错误代码. 获取返回值errorlevel的方法就是,在执行命令后,立马调用返回值errorlevel,如echo %errorlevel%或者if %errorlevel%==1等命令. errorlevel举例: =============================================== @echo off

基于Cesium1.26地图API下的GeoServer2.90服务器跨域设置

遇到的问题: 最近基于Cesium来做3D模型的地图开发,在访问自己发布的WMS服务之后,遇到了GeoServer跨域问题. 调用这个WMS服务的时候,浏览器(我用Chrome)开发者工具报错: 控制台提示如下: Font from origin 'http://xxxxxxxxxxxxx' has been blocked from loading by Cross-Origin Resource Sharing policy: No 'Access-Control-Allow-Origin'

3.26课&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;window.document对象

1.Window.document对象 一.找到元素:    docunment.getElementById("id"):根据id找,最多找一个:    var a =docunment.getElementById("id");将找到的元素放在变量中:    docunment.getElementByName("name"):根据name找,找出来的是数组:    docunment.getElementByTagName("na

2018-3-12 12周1次课 LNMP下的MySQL、PHP安装和配置

12.1 LNMP架构介绍 和LAMP不同的是,提供web服务的是Nginx 并且php是作为一个独立服务存在的,这个服务叫做php-fpm Nginx直接处理静态请求,动态请求会转发给php-fpm 用户并发支持很大,可以上好几万,Apache做不到 12.2 MySQL安装 [[email protected] ~]# cd /usr/local/src/ [[email protected] src]# wget http://mirrors.sohu.com/mysql/MySQL-5.

小学生趣味C++编程第26课 王宅六味

小学生c++编程资料 链接:https://pan.baidu.com/s/1FfOirxJ9rrY7rxtHUM4W_A 提取码:uqm9 #include<iostream> using namespace std; int main() { int n; cout<<"请输入编号:"; cin>>n; switch(n) { case 1: cout<<"寿仙菇"<<endl;break; case