行业知识
【C++】异常
2026-10-22 23:22:52
来源:互联网转载
异常
- 1.C语言传统的处理错误的方式
- 2.C++异常概念
- 3.异常的使用
- 4.自定义异常体系
- 5.C++标准库的异常体系
- 6.异常���优缺点
1.C语言传统的处理错误的方式
传统的错误处理机制:
- 终止程序,如assert,缺陷:用户难以接受。如发生内存错误,除0错误时就会终止程序。
- 返回错误码,缺陷:需要程序员自己去查找对应的错误。如系统的很多库的接口函数都是通过把错误码放到errno中,表示错误
实际中C语言基本都是使用返回错误码的方式处理错误,部分情况下使用终止程序处理非常严重的错误。
C++更喜欢用异常来处理错误。
2.C++异常概念
异常是一种处理错误的方式,当一个函数发现自己无法处理的错误时就可以抛出异常,让函数的直接或间接的调用者处理这个错误。
- throw: 当问题出现时,程序会抛出一个异常。这是通过使用 throw 关键字来完成的。
- catch: 在您想要处理问题的地方,通过异常处理程序捕获异常.catch 关键字用于捕获异常,可以有多个catch进行捕获。
- try: try 块中的代码标识将被激活的特定异常,它后面通常跟着一个或多个 catch 块。
thorw抛异常抛的的是一个任意类型对象。catch捕捉异常注意一定要类型匹配,否则就出错。
如果有一个块抛出一个异常,捕获异常的方法会使用 try 和 catch 关键字。try 块中放置可能抛出异常的代码,try 块中的代码被称为保护代码。使用 try/catch 语句的语法如下所示:
try{ // 保护的标识代码}catch( ExceptionName e1 ){ // catch 块}catch( ExceptionName e2 ){ // catch 块}catch( ExceptionName eN ){ // catch 块}我们先看看异常怎么用的,再说其他细节!
下面这段代码出现除0错误程序就会终止。但我不想让程序终止,因此当被除数为0就抛一个异常,很简单就是用throw后面加一个对象,可以是任意类型对象如int、string等等。后面catch对异常进行捕获。
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 try {Func();}catch (const char* errmsg){cout // 当b == 0时抛出异常if (b == 0)throw "Division by zero condition!";elsereturn ((double)a / (double)b);}void Func(){int len, time;cin len time;cout try {Func();}catch (char* errmsg)//抛出的是一个const char*,而catch这里是char*{cout cout // 当b == 0时抛出异常if (b == 0)throw "Division by zero condition!";elsereturn ((double)a / (double)b);}void Func(){try{int len, time;cin len time;cout cout try {Func();}catch (const char* errmsg){cout cout // 当b == 0时抛出异常if (b == 0)throw "Division by zero condition!";elsereturn ((double)a / (double)b);}void Func(){int* p = new int[10];int len, time;cin len time;cout try {Func();}catch (const char* errmsg){cout cout int* p = new int[10];try{int len, time;cin len time;cout cout // 当b == 0时抛出异常if (b == 0)throw "Division by zero condition!";elsereturn ((double)a / (double)b);}void Func(){int* p = new int[10];try{int len, time;cin len time;cout //cout try {Func();}catch (const char* errmsg){//记录日志,进行统一处理cout cout int* p = new int[10];try{int len, time;cin len time;cout //cout int* p = new int[10];try{int len, time;cin len time;cout cout // 当b == 0时抛出异常if (b == 0){string str("Division by zero condition!");throw str;//抛异常,抛出一个临时对象,出了作用域就销毁了}else{return ((double)a / (double)b);}}void Func(){int len, time;cin len time;cout try {Func();}catch (const string& s)//这里尽量用&,不然就是一个拷贝了{//这里捕获的s是临时对象str吗?//并不是,捕获的是str的拷贝。所以说的是类似于函数的传值返回//以前没有移动构造效率有点低,现在编译器在识别str会把它识别成一个将亡值就会调用移动构造效率还是可以的//不管是深拷贝还是移动构造,这里catch拿到的都是一个拷贝并不是本身。cout cout try {Func();}catch (int errid){cout try {Func();}catch (int errid){cout cout try {// 当b == 0时抛出异常if (b == 0){string str("Division by zero condition!");throw str;//抛string对象}else{return ((double)a / (double)b);}}catch (const string& s){cout public:Exception(const string& errmsg, int id):_errmsg(errmsg), _id(id){}virtual string what() const{return _errmsg;}protected:string _errmsg;int _id;};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;};srand(time(0));if (rand() % 7 == 0){throw SqlException("权限不足", 100, "select * from name = '张三'");}cout 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();}int main(){while (1){Sleep(1000);try {HttpServer();}catch (const Exception& e) // 这里捕获父类对象就可以{//满足多态调用,看父类的引用引用的是那个子类就调用那个子类的what()。就可以看到哪里出现问题,cout cout while (1){Sleep(1000);try {HttpServer();}catch (const Exception& e) // 这里捕获父类对象就可以{// 多态cout cout cout try {vectorcout cout while (1){Sleep(1000);try {HttpServer();}catch (const Exception& e) // 这里捕获父类对象就可以{// 多态cout cout cout // 用户名密码错误if (...)return 1;// 权限不足if (...)return 2;}int ServerStart() {if (int ret = ConnnectSql()
上一篇:服务器加固手册怎么写?
下一篇:惠普主机怎么接