C++内置了异常处理的语法元素 try catch

try语句处理正常代码逻辑

  • try语句发现异常时,则通过throw语句抛出异常,并退出try语句

catch语句处理异常情况

  • throw语句抛出异常时,则会直接跳到catch语句处理
  • catch语句允许被重载,在try语句后面可以有多个catch语句
  • 不同类型的异常由不同的catch语句捕获,顺序从上往下严格匹配,不会进行隐式转换,比如:
throw ;       //由int型的catch语句捕获
throw 1.5; //由double型的catch语句捕获
throw 1.5f; //由float型的catch语句捕获
throw 'A'; //由char型的catch语句捕获
throw "ABC"; //由char const *型的catch语句捕获
throw string("ABC"); //由string型的catch语句捕获
  • cath(...)语句,表示捕获前面所有没被定义的异常,且只能放在所有catch语句的末尾,比如:
    try
    {
throw 1.55; //直接退出try语句,跳转到满足条件的catch语句
throw "ERR";
    }
    catch(int i) //只捕获int型异常
    {
cout<<i<<endl;
    }
    catch(string s) //只捕获string型异常
    {
        cout<<s<<endl;
    }
    catch(...) //捕获前面所有没被定义的异常
    {
        cout<<"cath(...)"<<endl;
    }

运行打印:

cath(...)

throw抛出的异常必须被catch处理

如果throw抛出的异常,在当前函数没有catch语句能捕获,则会返回到上一级函数里再寻找catch语句,直到被处理为止,否则程序将结束运行,如下图:

在catch语句块中可以将捕获的异常重新抛出

catch抛出的异常,则需要通过外层的try...catch...捕获

如果是catch(...)语句,则直接填throw;即可,编译器会自动将捕获的异常重新抛出

比如:

void internal()
{
try
{
throw ;
}
catch(...)
{
cout<< "internal: catch(...)"<<endl;
throw;
}
} int main()
{ try
{
internal();
} catch(int i)
{
switch(i)
{
case : //1对应超时
cout<<"timeout"<<endl; break;
case : //2对应实参有误
cout<<"invalid argument"<<endl; break;
case : //3对应运行异常
cout<<"runtime exception"<<endl; break;
}
}
return ; }

运行打印:

internal: catch(...)
timeout

catch中重新抛出异常的意义

举个例子,当我们调用第三方库的func()函数,但是该func()函数返回的异常是int型,每个异常值意义大有不同 (每次查看异常值都需要翻看文档手册才行)

所以我们可以在自己库创建一个myfunc()函数,通过try...catch...再次封装func()函数,将异常值重新解释为其它类型(比如const char *),然后再次抛出.

以后调用myfunc()函数,获取的异常信息就是const char *类型了.

如果catch中抛出的类型是类的情况

  • 需要将捕获子类异常的catch放在上部
  • 捕获父类异常的cath放在下部, 避免子类异常当做父类异常来使用.

比如:

#include <iostream>
#include <string>
using namespace std; class Base
{
};
class Exception : public Base
{
int m_id; //异常值
string m_desc; //异常值描述信息
public:
Exception(int id, string desc)
{
m_id = id;
m_desc = desc;
}
int id() const
{
return m_id;
}
string description() const
{
return m_desc;
}
}; /*
假设: 当前的函数式第三方库中的函数,因此,我们无法修改源代码
函数名: void func(int i)
抛出异常的类型: int
-1 ==》 参数异常
-2 ==》 运行异常
-3 ==》 超时异常
*/
void func(int i)
{
if( i < )
{
throw -;
}
if( i > )
{
throw -;
}
if( i == )
{
throw -;
} cout << "Run func..." << endl;
} void MyFunc(int i)
{
try
{
func(i);
} catch(int i)
{
switch(i)
{
case -:
throw Exception(-, "Invalid Parameter"); //生成一个子类对象,并抛出
break; case -:
throw Exception(-, "Runtime Exception");
break; case -:
throw Exception(-, "Timeout Exception");
break;
}
}
} int main(int argc, char *argv[])
{
try
{
MyFunc();
} catch(const Exception& e) //捕获子类异常的catch放在上部
{
cout << "Exception Info: " << endl;
cout << " ID: " << e.id() << endl;
cout << " Description: " << e.description() << endl;
} catch(const Base& e) //捕获父类异常的catch放在下部
{
cout << "catch(const Base& e)" << endl;
}
return ;
}

运行打印:

Exception Info:
ID: -
Description: Timeout Exception

在C++标准库中提供了异常类

头文件 : <stdexcept>

标准库中的异常都是从exception类派生的

exception类主要有两个分支

- logic_error

用于程序中可避免的逻辑错误,在程序运行之前,就能被检测到

logic_error类派生了以下几种类:

  • domain_error(const string& )    :   专业领域内的范畴
  • invalid_argument(const string& )   :  无效参数,比如对unsigned型进行负数操作
  • length_error(const string& )  :    长度异常,比如字符串附加太多字符
  • out_of_range(const string&)     :    超出范围,比如数组下标越界
  • 它们都有一个what()成员函数,用来返回一个字符串异常信息

-runtime_error

常用于程序中无法避免的恶性错误,只在程序运行时才能被检测到

logic_error类派生了以下几种类:

  • range_error(const string& )  :内部计算时发生区间错误
  • overflow_error(const string& )  :算数运算时发生上溢
  • underflow_error(const string& )  :算数运算时发生下溢
  • 它们都有一个what()成员函数,用来返回一个字符串异常信息

比如:

#include <iostream>
#include <stdexcept>
using namespace std; template <typename T, int N >
class Array
{
T ma[N];public:
Array()
{
for(int i=;i<N;i++)
ma[N]=;
} T& operator [] (int index)
{
if((index>=)&&(index<N))
{
return ma[index];
} else //数组下标越界
{
throw out_of_range("T& operator [] (int index)"); //抛出一个 out_of_range类
}
}
}; int main()
{
try
{
Array<int,> arr;
arr[]=;
}
catch(out_of_range& exc)
{
cout<< exc.what()<<endl; //打印捕获到out_of_range类的异常信息
cout<< " Line: " << __LINE__ <<", Function: "<< __FUNCTION__ << endl; //打印当前行
}
return ;
}

运行打印:

T& operator [] (int index)
Line: , Function: main

29.C++- 异常处理的更多相关文章

  1. Java综合高级篇

    1.你用过哪些集合类? 大公司最喜欢问的Java集合类面试题 40个Java集合面试问题和答案 java.util.Collections 是一个包装类.它包含有各种有关集合操作的静态多态方法. ja ...

  2. C++异常处理的编程方法(阿愚,整整29集)

    相遇篇 <第1集 初次与异常处理编程相邂逅> <第2集 C++中异常处理的游戏规则> <第3集 C++中catch(…)如何使用> <第4集 C++的异常处理 ...

  3. Python 29 异常处理, 元类

    所学内容 异常处理(常用) AttributeError ··························  试图访问一个对象没有的树形,比如foo.x,但是foo没有属性xIOError ··· ...

  4. 29.2 Iterator 迭代器ConcurrentModificationException:并发修改异常处理

    /** Iterator:迭代器* * 需求:判断集合中是否包含元素java,如果有则添加元素android * Exception in thread "main" java.u ...

  5. Spring AOP实例——异常处理和记录程序执行时间

    实例简介: 这个实例主要用于在一个系统的所有方法执行过程中出线异常时,把异常信息都记录下来,另外记录每个方法的执行时间. 用两个业务逻辑来说明上述功能,这两个业务逻辑首先使用Spring AOP的自动 ...

  6. 七天学会ASP.NET MVC (六)——线程问题、异常处理、自定义URL

    本节又带了一些常用的,却很难理解的问题,本节从文件上传功能的实现引出了线程使用,介绍了线程饥饿的解决方法,异常处理方法,了解RouteTable自定义路径 . 系列文章 七天学会ASP.NET MVC ...

  7. Java异常处理和设计

    在程序设计中,进行异常处理是非常关键和重要的一部分.一个程序的异常处理框架的好坏直接影响到整个项目的代码质量以及后期维护成本和难度.试想一下,如果一个项目从头到尾没有考虑过异常处理,当程序出错从哪里寻 ...

  8. Atitit 跨平台异常处理(2)--------异常转换 -----java c# js异常对象结构比较and转换

    Atitit 跨平台异常处理(2)--------异常转换 -----java c# js异常对象结构比较and转换 { "@type":"java.lang.Runti ...

  9. Java7的异常处理新特性-addSuppressed()方法等

    开发人员对异常处理的try-catch-finally语句块都比较熟悉.如果在try语句块中抛出了异常,在控制权转移到调用栈上一层代码之前,finally语句块中的语句也会执行.但是finally语句 ...

随机推荐

  1. java实现中缀表达式转后缀表达式

    package postfix; import java.util.Stack; /** * * @author DELL 将中缀表达式转化为后缀表达式 */ public class Express ...

  2. Python之旅Day8 socket网络编程

    socket网络编程 Socket是网络编程的一个抽象概念.通常我们用一个Socket表示“打开了一个网络链接”,而打开一个Socket需要知道目标计算机的IP地址和端口号,再指定协议类型即可.soc ...

  3. VSCode插件开发全攻略(五)跳转到定义、自动补全、悬停提示

    更多文章请戳VSCode插件开发全攻略系列目录导航. 跳转到定义 跳转到定义其实很简单,通过vscode.languages.registerDefinitionProvider注册一个provide ...

  4. <mvc:annotation-driven> 中的HttpMessageConverters 的理解

    用烂的图 配置一个或多个HttpMessageConverter类型以用于转换@RequestBody方法 参数和@ResponseBody方法返回值. 使用此配置元素是可选的.  此处提供的Http ...

  5. 第一节:ASP.NET开发环境配置

    第一节:ASP.NET开发环境配置 什么是ASP.NET,学这个可以做什么,学习这些有什么内容? ASP.NET是微软公司推出的WEB开发技术. 2002年,推出第一个版本,先后推出ASP.NET2. ...

  6. outline和outline-offset属性实现简单的缝边效果

    如果现在有个需求,让你实现下面的样式,你会怎么做呢? 我首先想到的是用 border + box-shadow 实现,代码如下 div { margin: 50px auto; width: 200p ...

  7. 线性整流函数(ReLU)

    线性整流函数(Rectified Linear Unit, ReLU),又称修正线性单元, 是一种人工神经网络中常用的激活函数(activation function),通常指代以斜坡函数及其变种为代 ...

  8. centos7进入单用户模式

    当我们设置用户密码时,有可能会忘记,这时如何登陆呢,单用户模式就可以 首先我们进入开机界面,按e进行选择 会进入以下界面, 然后找到图中红线标注的该行,在行尾添加 init=/bin/sh 按住Ctr ...

  9. SpringBoot整合Mybatis完整版

    喜欢的朋友可以关注下,粉丝也缺. 自从Spring推出Boot,Cloud系列之后,一度成为热门的框架,现在大部分的招聘要求都要有相关的开发经验,借此我在这里就给大家分享一下如何玩转SpringBoo ...

  10. iReport 5.6.0 PDF导出中文不显示问题 解决方案

    问题描述 iReport 5.6.0 PDF格式导出,中文不显示. 报错信息如下: Error exporting print... Could not load the following font ...