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

宁波网站制作费用网页制作与设计项目策划书

宁波网站制作费用,网页制作与设计项目策划书,中装建设股票行情,云南省建设厅官方网站证书目录 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://www.dtcms.com/a/413733.html

相关文章:

  • 钱宝网站怎么做任务软文推广营销服务平台
  • 广西贵港建设集团有限公司网站自己想做网站
  • 怎样建外贸网站网站开发 沈阳
  • 网站建设可上传视频的wordpress编辑主体
  • 开封网站建设公司排名网站建设方案模板
  • 怎么做建设网站商城网站建设php
  • 网站域名 被别人备案广东网站建设专业公司排名
  • 酒店网站的建设方案网站建设和网站设计公司在哪里
  • 泉州网站建设方案详细长春火车站需要核酸检测报告吗
  • 亲子游网站怎么做服装网站建设建议
  • 个人站长网站asp 手机网站
  • 同一家公司可以做几个网站吗山东seo推广平台
  • 济南饰品行业网站开发互联网广告推广是什么
  • 免费网站建站w网页版浏览器怎么设置
  • 泰安公司网站开发全屏式网站
  • 专用网站建设永久免费自助建站系统
  • 学校网站建设基本流程深圳服装设计学院
  • 合肥生态建设职业培训学校网站甘肃网站建站系统平台
  • 云南响应式网站建设正规自媒体培训学校
  • 做水暖的网站网络推广的方式有哪些
  • 怎么才能有自己的网站外贸进口流程
  • 云岭建设集团的网站如何替换wordpress
  • 盐城网站建设公司公司做网站需要哪些内容
  • 网站 功能需求wordpress登录按钮设置
  • 网站如何做才会有流量php做网站的支付功能
  • 怎么在建设银行网站购买国债网站建设的专业知识
  • 网站模板 html5专业的丹阳网站建设
  • 网站开发质量管理建设淘宝网站需要多少钱
  • ext做的网站网站备案 更名
  • 网站转移 备案织梦如何做汽车贸易网站