当前位置: 首页 > wzjs >正文

90设计网站官网杭州网站建设出 名

90设计网站官网,杭州网站建设出 名,做网站收入太低,查看域名之前做的网站目录 1、异常的概念及使用 1.1 异常的概念 1.2 异常的抛出和捕获 1.3 栈展开 1.4 查找匹配的处理代码 1.5 异常的重新抛出 1.6 异常的安全问题 1.7 异常的规范 2、标准库的异常(了解) 1、异常的概念及使用 1.1 异常的概念 C语言,出错了,就报错…

目录

1、异常的概念及使用

1.1 异常的概念

1.2 异常的抛出和捕获

1.3 栈展开

1.4 查找匹配的处理代码

1.5 异常的重新抛出

1.6 异常的安全问题

1.7 异常的规范

2、标准库的异常(了解)


1、异常的概念及使用

1.1 异常的概念

C语言,出错了,就报错误码,还要去查询错误信息,比较麻烦。错误处理与正常逻辑混杂,容易遗漏检查。

C++,出错了,就(throw)抛出一个异常对象,包含更全面的错误信息,并且(try)检测错误和(catch)处理错误,分开进行

1.2 异常的抛出和捕获

当程序出现问题时,可以通过抛出(throw一个异常对象来触发异常处理机制。该对象的类型及当前的调用链共同决定了哪个catch处理此异常

异常处理流程

  1. 匹配规则
    被选中的处理代码是调用链中与该异常对象类型匹配(通过类型匹配规则),且距离抛出位置最近catch

  2. 信息传递
    通过异常对象成员变量返回what()的字符串传递错误信息

  3. 控制流转移

    • throw执行时其后的语句不再执行

    • 程序throw跳转匹配的catch,该catch可能在当前函数或调用链上游的某个函数中。

    • 控制权转移意味着:

      • 调用链中的函数可能提前退出(函数栈帧提前销毁)(栈展开,Stack Unwinding)。

      • 栈上已构造的局部对象会按创建顺序的逆序销毁(RAII保证)。

  4. 异常对象生命周期

    • 因为异常对象是局部的(类似函数值返回的临时对象),会调用移动构造,(若没有移动构造,就调用拷贝构造)。

    • 移动(或复制)对象在匹配的catch块结束时 销毁

1.3 栈展开

抛出异常后,程序暂停当前函数的执行

如果 throw try 块内部查找匹配的 catch 语句如果匹配的,则跳到 catch 的地方进行处理

如果当前函数没有 try/catch 子句,或者有 catch 子句但是类型不匹配,则退出当前函数,继续在外层调用函数链中查找,上述查找的 catch 过程被称为栈展开

如果到达 main 函数,依旧没有找到匹配的 catch 子句,程序会调用标准库的 terminate 函数终止程序

如果找到匹配的 catch 子句处理后当前 catch 子句后面的代码继续执行

1.4 查找匹配的处理代码

一般情况下,抛出对象catch类型匹配的,如果有多个类型匹配的,就选择最近的catch

允许一些例外类型转换:

非常量 -> 常量(即权限缩小),

数组->数组元素的指针

函数->函数指针

派生类->基类,这个非常实用

如果到main函数异常仍旧没有被匹配就会终止程序我们是不期望程序终止,所以一般main函数中最后都会使用catch(...),它可以捕获任意类型的异常但是不知道异常错误是什么

#include <iostream>
#include <string>
#include <thread>
#include <chrono>
#include <ctime>
#include <cstdlib>// 一般大型项目程序才会使用异常,下面我们模拟设计一个服务的几个模块
// 每个模块的异常都是 Exception 的派生类,每个模块可以添加自己的数据
// 最后捕获时,我们捕获基类就可以class Exception {
public:Exception(const std::string& errmsg, int id): _errmsg(errmsg), _id(id) {}virtual std::string what() const {return _errmsg;}int getid() const {return _id;}protected:std::string _errmsg;int _id;
};class SqlException : public Exception {
public:SqlException(const std::string& errmsg, int id, const std::string& sql): Exception(errmsg, id), _sql(sql) {}std::string what() const override {std::string str = "SqlException:";str += _errmsg;str += "->";str += _sql;return str;}private:const std::string _sql;
};class CacheException : public Exception {
public:CacheException(const std::string& errmsg, int id): Exception(errmsg, id) {}std::string what() const override {std::string str = "CacheException:";str += _errmsg;return str;}
};class HttpException : public Exception {
public:HttpException(const std::string& errmsg, int id, const std::string& type): Exception(errmsg, id), _type(type) {}std::string what() const override {std::string str = "HttpException:";str += _type;str += ":";str += _errmsg;return str;}private:const std::string _type;
};void SQLMgr() {if (rand() % 7 == 0) {throw SqlException("权限不足", 100, "select * from name = '张三'");} else {std::cout << "SQLMgr 调用成功" << std::endl;}
}void CacheMgr() {if (rand() % 5 == 0) {throw CacheException("权限不足", 100);} else if (rand() % 6 == 0) {throw CacheException("数据不存在", 101);} else {std::cout << "CacheMgr 调用成功" << std::endl;}SQLMgr();
}void HttpServer() {if (rand() % 3 == 0) {throw HttpException("请求资源不存在", 100, "get");} else if (rand() % 4 == 0) {throw HttpException("权限不足", 101, "post");} else {std::cout << "HttpServer 调用成功" << std::endl;}CacheMgr();
}int main() {srand(time(0));while (1) {std::this_thread::sleep_for(std::chrono::seconds(1));try {HttpServer();}catch (const Exception& e) {  // 这里捕获基类,基类对象和派生类对象都可以被捕获std::cout << e.what() << std::endl;}catch (...) {std::cout << "Unkown Exception" << std::endl;}}return 0;
}

1.5 异常的重新抛出

有时catch到一个异常对象后,需要对错误进行分类,其中的某种异常错误需要进行特殊的处理其他错误则重新(throw)抛出异常外层调用链处理。捕获异常后需要重新抛出,直接 throw; 就可以把捕获的对象直接抛出。

#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>using namespace std;// 下面程序模拟展示了聊天时发送消息,发送失败捕获异常
// 可能在电梯地下室等场景手机信号不好,需要多次尝试
// 如果多次尝试都发送不出去,则需要捕获异常再重新抛出
// 如果不是网络差导致的错误,捕获后也要重新抛出class Exception {
public:Exception(const string& errmsg, int id): _errmsg(errmsg), _id(id) {}virtual string what() const {return _errmsg;}int getid() const {return _id;}protected:string _errmsg;int _id;
};class HttpException : public Exception {
public:HttpException(const string& errmsg, int id, const string& type): Exception(errmsg, id), _type(type) {}string what() const override {string str = "HttpException:";str += _type;str += ":";str += _errmsg;return str;}private:const string _type;
};void _SendMsg(const string& s) {if (rand() % 2 == 0) {throw HttpException("网络不稳定,发送失败", 102, "put");}else if (rand() % 7 == 0) {throw HttpException("你已经不是对方的好友,发送失败", 103, "put");}else {cout << "发送成功" << endl;}
}void SendMsg(const string& s) {// 发送消息失败,则再重试3次for (size_t i = 0; i < 4; i++) {try {_SendMsg(s);break;}catch (const Exception& e) {// 捕获异常,如果是102号错误(网络不稳定),则重新发送// 如果不是102号错误,则将异常重新抛出if (e.getid() == 102) {// 重试三次以后还是失败,则说明网络太差,重新抛出异常if (i == 3) {throw;}cout << "开始第" << i + 1 << "次重试" << endl;}else {throw;}}}
}int main() {srand(time(0));string str;while (cin >> str) {try {SendMsg(str);}catch (const Exception& e) {cout << e.what() << endl << endl;}catch (...) {cout << "Unknown Exception" << endl;}}return 0;
}

如果是102号错误,这个异常不处理,出了catch子句,自动析构,再尝试发送。

1.6 异常的安全问题

异常抛出后后面的代码就不再执行,前面申请了资源(内存、锁等),后面进行释放,但是中间可能会抛异常就会导致资源没有释放,这里由于异常就引发了资源泄漏,产生安全性的问题。解决方案:

1. 可以中间捕获异常释放资源后再重新抛出麻烦

2. 后面的智能指针章节讲的RAII方式解决这种问题更方便

其次析构函数中,如果抛出异常也要谨慎处理,比如析构函数要释放10个资源,释放到第5个时抛出异常,则也需要捕获处理,否则后面的5个资源就没释放,也资源泄漏了。《Effective C++》第8个条款也专门讲了这个问题,别让异常逃离析构函数。

1.7 异常的规范

对于用户和编译器而言,预先知道某个程序会不会抛出异常大有裨益,有助于简化代码

C++98中函数参数列表的后面接throw(),表示函数不抛异常,函数参数列表的后面接throw(类型1, 类型2...)表示可能会抛出多种类型的异常,可能会抛出的类型用逗号分割。

C++98的方式这种方式过于复杂,实践中并不好用,C++11中进行了简化函数参数列表后面noexcept表示不会抛出异常

编译器不会在编译时检查noexcept,也就是说如果一个函数noexcept修饰了,但是同时又包含了throw语句或者调用的函数可能会抛出异常编译还是会顺利通过的(有些编译器可能会报个警告)。但是一个声明了noexcept的函数 抛出了异常,程序会调用terminate终止程序

noexcept(expression)还可以作为一个运算符去检测一个表达式 是否会抛出异常可能会则返回false不会就返回true

一般外层处理异常

#include <iostream>
using namespace std;double Divide(int a, int b) // noexcept
{// 当 b == 0 时抛出异常if (b == 0){throw "Division by zero condition!";}return (double)a / (double)b;
}int main()
{try{int len, time;cin >> len >> time;cout << Divide(len, time) << endl;}catch (const char* errmsg){cout << errmsg << endl;}catch (...){cout << "Unknown Exception" << endl;}int i = 0;cout << noexcept(Divide(1, 2)) << endl; // 0cout << noexcept(Divide(1, 0)) << endl; // 0cout << noexcept(++i) << endl; // 1return 0;
}

2、标准库的异常(了解)

exception - C++ Reference

不好用,公司一般自己实现异常库。


文章转载自:

http://t3UkYbD7.jsLzh.cn
http://f0MqiQhQ.jsLzh.cn
http://LNZcbnd3.jsLzh.cn
http://0qN7mlyc.jsLzh.cn
http://cYxGYHJ1.jsLzh.cn
http://DGAbNgLk.jsLzh.cn
http://kXoMJEIs.jsLzh.cn
http://adFrMYm5.jsLzh.cn
http://OHipwb49.jsLzh.cn
http://iK6mOXdL.jsLzh.cn
http://jhFqGtJ8.jsLzh.cn
http://a8100Jy0.jsLzh.cn
http://kLSZwGmz.jsLzh.cn
http://tnfX012a.jsLzh.cn
http://ccURckiU.jsLzh.cn
http://p5TzdQas.jsLzh.cn
http://cdpMNZhJ.jsLzh.cn
http://D5E3wqHM.jsLzh.cn
http://A3amB82P.jsLzh.cn
http://hpeJyIIv.jsLzh.cn
http://5fyJir9F.jsLzh.cn
http://5pCOgGq1.jsLzh.cn
http://4qXuxhu0.jsLzh.cn
http://gupv4Bgy.jsLzh.cn
http://AFsPbMnY.jsLzh.cn
http://0tDClDg2.jsLzh.cn
http://GV8hyjFT.jsLzh.cn
http://rLCrXPJ7.jsLzh.cn
http://xTCosqZQ.jsLzh.cn
http://twI7xs10.jsLzh.cn
http://www.dtcms.com/wzjs/654121.html

相关文章:

  • 昆明网站推广咨询平台网站建设及推广费用
  • 假网站怎么制作电子商务网站建设报价
  • 滁州网站建设hi444wordpress和jwplayer
  • 网站兼容做封面的网站
  • 浏览器大全网站如何做网页链接
  • 烟台网站排名优化报价网站php文件上传
  • 成都家居网站建设电商设计用什么软件
  • 定制程序网站网站开发工具 知乎
  • 南京网站建设方案宾馆管理系统
  • 网页制作与网站建设宝典扫描版pdf太原百度网站排名优化
  • thinkphp制作网站开发大连软件培训
  • 域名备案后怎样做网站西安网站建设风尚
  • 重庆门户网站有哪些成品网站免费下载
  • 慈溪网站制作杭州公司申请车牌需要什么条件
  • 淘宝网站经营与建设论文东莞市营销网站建设
  • 个人网站取名手机网站建设的第一个问题
  • 广州做网站比较有名的公司wordpress添加新页面
  • 怎么找到仿牌外贸出口公司的网站贵州定制型网站建设
  • 商城网站建设预算WordPress旋转图标
  • 外国网站上做雅思考试网站推广的资源合作推广
  • 工业设计网站 知乎wordpress 可以多用户
  • 汽车最全的网站什么是网站名称文件夹
  • 做任务领积分兑换别的网站上的会员租房子做民宿在哪个网站
  • 空气炸锅做糕点的网站虚拟空间软件下载
  • 专业柳州网站建设价格cute wordpress主题
  • 开公司可以在哪些网站做推广gta5买办公室 网站正在建设
  • 58同城济南网站建设南通网站建设机构
  • 青岛中小企业建设网站有扶持资金吗手机网站制作良心服务
  • 全球云邮登陆网站淄博网站设计制作
  • 废品网站怎么做公众号怎么开通留言功能