当前位置:网站首页>异常的了解
异常的了解
2022-08-10 21:05:00 【GracefulBlack】
C语言传统处理错误
- 返回错误码 , 缺陷:返回一个错误数字编号,不知道是哪个错误,很难受,还需要查错误码表
- 终止程序,比如assert,缺陷:有点太激进了,遇到了某个错误直接崩溃

C++异常
概念

用法
- catch的代码不是顺序执行的,没有异常的情况,catch的代码直接就跳过了
- 代码出现异常时,代码不是顺序执行的,会直接跳到捕获它的地方

#include<iostream>
#include<string>
#include<time.h>
#include <thread>
#include <vector>
using namespace std;
double Division(int a, int b)
{
// 当b == 0时抛出异常
if (b == 0)
throw "Division by zero condition!";
else
return ((double)a / (double)b);
}
void Func1()
{
try
{
int len, time;
cin >> len >> time;
cout << Division(len, time) << endl;
}
catch (int errid)
{
cout << errid << endl;
}
}
void Func2()
{
int len, time;
cin >> len >> time;
if (time != 0)
{
throw 1;
}
else
{
cout << len << " " << time << endl;
}
}
int main()
{
try
{
Func1();
Func2();
}
catch (const char* errmsg)
{
cout << errmsg << endl;
}
catch (int errid)
{
cout << errid << endl;
}
catch (...)
{
cout << "unkown exception" << endl;
}
return 0;
}
- 如果抛出异常对象,抛出的是异常对象的拷贝,因为这个对象可能是临时生成的,拷贝的临时对象会在catch以后销毁
double Division(int a, int b)
{
// 当b == 0时抛出异常
if (b == 0)
{
string str("除零错误");
throw str;
}
else
{
return ((double)a / (double)b);
}
}
void Func1()
{
int len, time;
cin >> len >> time;
cout << Division(len, time) << endl;
}
int main()
{
try
{
Func1();
}
catch (const string& errmsg)
{
cout << errmsg << endl;
}
return 0;
}
- 如果抛出的异常没有被捕获掉,那么程序就会被终止
- catch(…)的意思是捕获任意类型

- 被捕获后下面的func2会继续执行 , catch以后的子句是会继续执行的
double Division(int a, int b)
{
// 当b == 0时抛出异常
if (b == 0)
{
string str("除零错误");
throw str;
}
else
{
return ((double)a / (double)b);
}
}
void Func2()
{
int len, time;
cin >> len >> time;
if (time != 0)
{
throw 3.33;
}
else
{
cout << len << " " << time << endl;
}
}
void Func1()
{
try
{
int len, time;
cin >> len >> time;
cout << Division(len, time) << endl;
}
catch (const string& errmsg)
{
cout << errmsg << endl;
}
Func2();
}
int main()
{
try
{
Func1();
}
catch (const string& errmsg)
{
cout << errmsg << endl;
}
catch (int errid)
{
cout << errid << endl;
}
catch (...)
{
cout << "未知异常" << endl;
}
return 0;
}
代码二
double Division(int a, int b)
{
// 当b == 0时抛出异常
if (b == 0)
{
throw "Division by zero condition!";
}
return (double)a / (double)b;
}
void Func()
{
// 这里可以看到如果发生除0错误抛出异常,另外下面的array没有得到释放。
// 所以这里捕获异常后并不处理异常,异常还是交给外面处理,这里捕获了再
// 重新抛出去。
int* array = new int[10];
int len, time;
cin >> len >> time;
try
{
cout << Division(len, time) << endl;
}
catch (...) // 拦截异常,不是要处理异常,而是要正常释放资源
{
cout << "delete []" << array << endl;
delete[] array;
throw; // 捕获到什么对象就重新抛出什么对象
}
cout << "delete []" << array << endl;
delete[] array;
}
int main()
{
try
{
Func();
}
catch (const char* errmsg)
{
cout << errmsg << endl;
// 记录日志
}
return 0;
}
自定义异常体系
- 服务器开发中通常使用的异常继承体系
// 服务器开发中通常使用的异常继承体系
class Exception
{
public:
Exception(const string& errmsg, int id)
:_errmsg(errmsg)
, _id(id)
{
}
virtual string what() const
{
return _errmsg;
}
protected:
string _errmsg;
int _id;
};
class SqlException : public Exception
{
public:
SqlException(const string& errmsg, int id, const string& sql)
:Exception(errmsg, id)
, _sql(sql)
{
}
virtual string what() const
{
string str = "SqlException:";
str += _errmsg;
str += "->";
str += _sql;
return str;
}
private:
const string _sql;
};
class CacheException : public Exception
{
public:
CacheException(const string& errmsg, int id)
:Exception(errmsg, id)
{
}
virtual string what() const
{
string str = "CacheException:";
str += _errmsg;
return str;
}
};
class HttpServerException : public Exception
{
public:
HttpServerException(const string& errmsg, int id, const string& type)
:Exception(errmsg, id)
, _type(type)
{
}
virtual string what() const
{
string str = "HttpServerException:";
str += _type;
str += ":";
str += _errmsg;
return str;
}
private:
const string _type;
};
void SQLMgr()
{
srand(time(0));
if (rand() % 7 == 0)
{
throw SqlException("权限不足", 100, "select * from name = '张三'");
}
//throw "xxxxxx";
}
void CacheMgr()
{
srand(time(0));
if (rand() % 5 == 0)
{
throw CacheException("权限不足", 100);
}
else if (rand() % 6 == 0)
{
throw CacheException("数据不存在", 101);
}
SQLMgr();
}
void HttpServer()
{
// ...
srand(time(0));
if (rand() % 3 == 0)
{
throw HttpServerException("请求资源不存在", 100, "get");
}
else if (rand() % 4 == 0)
{
throw HttpServerException("权限不足", 101, "post");
}
CacheMgr();
}
void ServerStart()
{
while (1)
{
this_thread::sleep_for(chrono::seconds(1));
try {
HttpServer();
}
catch (const Exception& e) // 这里捕获父类对象就可以
{
// 多态
cout << e.what() << endl;
}
catch (...)
{
cout << "Unkown Exception" << endl;
}
}
}
int main()
{
ServerStart();
return 0;
}

异常安全
- 最好不要在构造函数里抛 ->对象可能会不完整或没有完全初始化
- 最好不要在析构函数里抛 ->可能导致资源泄漏(内存泄漏,句柄未关闭等)

异常规范
- thow ()里面如果有异常类型,那么就是该函数可能抛出的所i有类型
- 函数后面跟throw() ,括号里面是空的,表示函数不抛异常,但在C++11中更喜欢用noexcept
- 无接口说明,那么说明可以抛任何异常
- 不过在实际中可能用的并不标准,在实际中很难执行,也有可能有人写了但却偷偷抛异常


异常的优缺点(考点)
优点:
- 精确的展示出错误的各种信息,可以更好的定位bug
- 调用链很深,最外层拿到错误很困难
- 第三方库需要用到用到异常
- 有些经典函数不能使用错误码(比如本身就要返回一个值)

缺点: - 执行流乱跳,就像以前的建议少使用goto(重要)
- 有一定的性能开销,但可以忽略不计(以前返回一个错误码,现在返回一个对象,还有堆栈的开销)(不是很重要)
- 没有垃圾回收机制,学习成本搞 ->RAII->只能智能指针,lock_guard (很重要)
- C++的异常体系定义的不好(不是很重要)

总的来说,利大于弊 ,OO
边栏推荐
猜你喜欢

【Windows】你不能访问此共享文件夹,因为你组织的安全策略阻止未经身份验证的来宾访问,这些策略可帮助保护你的电脑

使用SylixOS虚拟串口,实现系统串口自由

C. Even Picture

石油化工行业商业供应链管理系统:标准化供应商管理,优化企业供应链采购流程

npm warn config global `--global`, `--local` are deprecated. use `--location=global` instead.

找的笔试题的复盘(一)

C#【必备技能篇】Hex文件转bin文件的代码实现

数字化转型:如何引导创新领导者

这些不可不知的JVM知识,我都用思维导图整理好了

LeetCode-36-二叉搜索树与双向链表
随机推荐
Live Classroom System 09--Tencent Cloud VOD Management Module (1)
[Golang]如何优雅管理系统中的几十个UDF(API)
Before implementing MES management system, these three questions to consider
wget编译升级故障解决
Live Classroom System 08 Supplement - Tencent Cloud Object Storage and Course Classification Management
带你一文读懂SaaS版多租户商城系统对多品牌企业的应用价值
Are you hungry - Institution tree radio
Date picker component (restrict year to set only displayed months)
每次打开chrome会跳出What's new
微擎盲盒交友变现-vp_ph打开慢优化
ACM解题笔记——HDU 1401 Solitaire(DBFS)
PostgreSQL 介绍
Object.assign用法 以及 与$.extend的区别
力扣215题,数组中的第K个最大元素
The use of TortoiseSVN little turtle
Auto.js中APP应用相关指令
In 2021 China industrial Internet security competition (competition) in fujian province and the first industry of fujian province Internet innovation competition
2021 CybricsCTF
ArcGIS自动随机生成采样点的方法
如何提高代码的可读性 学习笔记