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

24.异常

一.C语言传统的处理错误的方式

在设计C语言的时候,我们要独立设计一些错误码进行返回

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<thread>
#include <ctime>
#include <ratio>
#include <chrono>
using namespace std;int main()
{FILE* fout = fopen("Test.txt", "r");cout << fout << endl;cout << errno << endl;perror("fopen fail");return 0;
}

系统识别的错误码对应得错误信息

二. C++异常概念

三.异常的使用

1.异常的抛出和捕获

double Division(int a, int b)
{// 当b == 0时抛出异常if (b == 0)throw "Division by zero condition!";elsereturn ((double)a / (double)b);
}void Func()
{int len, time;cin >> len >> time;cout << Division(len, time) << endl;cout << len << " " << time << endl;
}int main()
{try {Func();}catch (const char* errmsg) {cout << errmsg << endl;}catch(...){cout<<"unkown exception"<<endl;}return 0;
}

try catch没有抛出异常是不会进去的,只有我们抛出异常,才会进去,没有抛出异常,直接就进行跳过

double Division(int a, int b)
{// 当b == 0时抛出异常if (b == 0){string s("Division by zero condition!");throw s;}else{return ((double)a / (double)b);}
}void Func()
{int len, time;cin >> len >> time;try{cout << Division(len, time) << endl;}catch (size_t x){cout << x << endl;}cout << "xxxxxxxxxxxxxxxxxxxxx" << endl;
}int main()
{while (1){try{Func();}catch (const string& errmsg){cout << errmsg << endl;}catch (...){cout << "unkown exception" << endl;}}return 0;
}

double Division(int a, int b)
{// 当b == 0时抛出异常if (b == 0){string s("Division by zero condition!");throw s;}else{return ((double)a / (double)b);}
}void Func()
{int len, time;cin >> len >> time;try{cout << Division(len, time) << endl;}catch (size_t x){cout << x << endl;}catch (const char* errmsg){cout << errmsg << endl;}cout << "xxxxxxxxxxxxxxxxxxxxx" << endl;
}int main()
{while (1){try{Func();}catch (const string& errmsg){cout << errmsg << endl;}catch (...){cout << "unkown exception" << endl;}}return 0;
}

如果一个捕获的都没有的话,程序就会出现异常

double Division(int a, int b)
{// 当b == 0时抛出异常if (b == 0){string s("Division by zero condition!");throw s;}else{return ((double)a / (double)b);}
}
void Func()
{int len, time;cin >> len >> time;try{cout << Division(len, time) << endl;}catch (size_t x){cout << x << endl;}catch (const char* errmsg){cout << errmsg << endl;}cout << "xxxxxxxxxxxxxxxxxxxxx" << endl;
}
int main()
{while (1){try{Func();}catch (const string& errmsg){cout << errmsg << endl;}catch (...){cout << "unkown exception" << endl;}}return 0;
}

2.捕获任意的异常

try{Func();}catch (const string& errmsg){cout << errmsg << endl;}catch (...){cout << "unkown exception" << endl;}

我们一般是不会抛一些字符串,整性啥的(和C语言本质上没啥改变),而是抛出一个自定义类型(包含信息错误描述 + 编号等)

我们还可以通过日志等来进行操作

3.异常不受隐式类型转换的影响

如果我们抛出上面这种异常,我们来进行接收(不能走隐式类型转换)

类型匹配一定要严格匹配,不能进行隐式类型转换

4.捕获异常不一定要类型完全一样

下面有一个案例(  服务器开发中通常使用的异常继承体系  ):

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<thread>
#include <ctime>
#include <ratio>
#include <chrono>
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 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()
{if (rand() % 7 == 0){throw SqlException("权限不足", 100, "select * from name = '张三'");}cout << "调用成功" << endl;
}void CacheMgr()
{if (rand() % 5 == 0){throw CacheException("权限不足", 100);}else if (rand() % 6 == 0){throw CacheException("数据不存在", 101);}SQLMgr();
}void seedmsg(const string& s)
{//cout << "void seedmsg(const string& s)" << endl;//throw HttpServerException("网络不稳定,发送失败", 102, "put");if (rand() % 2 == 0){ throw HttpServerException("网络不稳定,发送失败", 102, "put");}else if (rand() % 3 == 0){throw HttpServerException("你已经不是对象的好友,发送失败", 103, "put");}else{cout << "发送成功" << endl;}
}void HttpServer()
{/*if (rand() % 3 == 0){throw HttpServerException("请求资源不存在", 100, "get");}else if (rand() % 4 == 0){throw HttpServerException("权限不足", 101, "post");}*/// 失败以后,再重试3次for (size_t i = 0; i < 4; i++){try{seedmsg("今天一起看电影吧");break;}catch (const Exception& e){if (e.getid() == 102){if (i == 3)throw e;cout << "开始第" << i+1 << "重试" << endl;}else{throw e;}}}CacheMgr();
}int main()
{srand(time(0));while (1){this_thread::sleep_for(chrono::seconds(1));try {HttpServer();}catch (const Exception& e) // 这里捕获父类对象就可以{using std::chrono::system_clock;// 多态system_clock::time_point today = system_clock::now();std::time_t tt = system_clock::to_time_t(today);cout << ctime(&tt) << e.what() << endl << endl;}catch (...){cout << "Unkown Exception" << endl;}}return 0;
}

上面那个样例,有两个点要进行理解:

1.我们在不同的模块,可以抛出对应得错误,这样我们能根据抛出错误得信息进行分析

2.我们在接收到异常的时候,我们不想处理,我们可以再次进行抛出

四.异常的安全

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* array1 = new int[10];int* array2 = new int[10];   int len, time;cin >> len >> time;cout << Division(len, time) << endl;// ...cout << "delete []" << array1 << endl;delete[] array1;cout << "delete []" << array2 << endl;delete[] array2;
}int main()
{try{Func();}catch (const char* errmsg){cout << errmsg << 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];try {int len, time;cin >> len >> time;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;
}

这个地方不是为了将我们捕获到的异常进行处理,而是为了解决我们的内存泄漏问题

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* array1 = new int[10];int* array2 = new int[10];   // 抛异常呢try{int len, time;cin >> len >> time;cout << Division(len, time) << endl;}catch (...){cout << "delete []" << array1 << endl;cout << "delete []" << array2 << endl;delete[] array1;delete[] array2;throw; // 异常重新抛出,捕获到什么抛出什么}// ...cout << "delete []" << array1 << endl;delete[] array1;cout << "delete []" << array2 << endl;delete[] array2;
}int main()
{try{Func();}catch (const char* errmsg){cout << errmsg << endl;}return 0;
}

上面这段程序还是会存在我们的异常:

所以,我们的new也是会进行抛异常的,但是这样我们代码写起来就不优雅了(太冗余了)

后续我们可以使用智能指针来解决这种问题

double Division(int a, int b)
{// 当b == 0时抛出异常if (b == 0){throw "Division by zero condition!";}return (double)a / (double)b;
}struct A
{~A() noexcept{cout << "~A()" << endl;}int _a1 = 0;int _a2 = 0;
};template<class T>
class SmartPtr
{
public:// RAIISmartPtr(T* ptr):_ptr(ptr){}~SmartPtr(){delete _ptr;}// 重载运算符,模拟指针的行为T& operator*(){return *_ptr;}T* operator->(){return _ptr;}
private:T* _ptr;
};void Func()
{// 更好解决方案是智能指针shared_ptr<A> sp1(new A);shared_ptr<A> sp2(new A);sp1->_a1++;sp1->_a2++;shared_ptr<A> sp3(sp1);int len, time;cin >> len >> time;cout << Division(len, time) << endl;
}int main()
{try{Func();}catch (const char* errmsg){cout << errmsg << endl;}catch (const exception& e){cout << e.what() << endl;}catch (...){cout << "未知异常"<< endl;}return 0;
}

五.异常规范

noexcept  关键字:

确定不抛异常的,就不用加  noexcept  关键字

六.自定义异常体系

七.C++标准库的异常体系

int main()
{try{vector<int> v(10, 5);// 这里如果系统内存不够也会抛异常v.reserve(1000000000);// 这里越界会抛异常v.at(10) = 100;}catch (const exception& e) // 这里捕获父类对象就可以{cout << e.what() << endl;}catch (...){cout << "Unkown Exception" << endl;}return 0;
}

如 out_of_range() 的使用:

八.异常的优缺点

1.优点

2.缺点

总结:

http://www.dtcms.com/a/521409.html

相关文章:

  • Linux用户管理命令详解
  • STM32F4串口通信乱码
  • 网站虚拟交易技术怎么做大型新型网站
  • 易讯网站建设为企业做网站
  • vLLM/Docker 部署Qwen2.5-VL-32B模型
  • 广州设计网站建设电子商务网站建设与维护考试题
  • 单片机的开发(未完待续,有时间写)
  • 酒店内容推荐系统:这5个技术坑90%的人都踩过!
  • 定制型网站开发网站建设服务哪便宜
  • 十大下载网站免费安装网站扫二维码怎么做
  • 口碑好的合肥网站建设多说wordpress
  • JetPack 6系统中,默认启用的自动更新机制不完全依赖 unattended-upgrades 包
  • 企业网站开发服务器山东兴华建设集团网站
  • 建设工程网上质检备案网站中英文网站如何做思路
  • 网站不排名一切等于零今天的新闻直播
  • 学seo网站推广好吗网站用户建设的设计与实现
  • 滇中引水工程建设管理局网站安卓aso优化
  • 盐城网站开发招代理松江车墩网站建设
  • asp.net企业网站后台管理系统企业管理软件系统网
  • 现在手机网站用什么做wordpress推广码
  • POI的概念解析及电子地图与POI的联系和区别分析
  • 建什么网站 做 cpa服务器搭建网站环境
  • **标题:发散创新:智能交通系统的深度探究与实现**摘要:本文将详细
  • DDIM(Diffusion)个人总结
  • Radamsa的TCP客户端/服务器模式用法
  • 【Flutter 问题系列第 86 篇】解决 Google Play 提示应用必须支持 16 KB 内存页面大小问题的方案
  • 南京网站设计建设公司电话添加网站描述
  • 网站建设具体步骤应该怎么做ps怎么制作网页
  • 此网站无法提供安全连接 建设银行seo在线优化排名
  • 网站 架构 设计企业做营销网站