一、概念

异常:存在于运行时的反常行为,这些行为超过了函数的正常的功能范围。

异常处理:处理程序中的错误,异常处理机制为程序中异常检测和异常处理这两部分的协作提供支持。

在C++中,异常处理包括:

  • throw表达式,表示遇到了无法处理的问题
  • try语句块,处理异常;以关键字try开始,一个或多个catch结束
  • 一套异常类,用于在throw表达式和相关的catch子句之间传递异常的信息。

二、异常的好处

  1. 整性返回值没有语义信息,而异常包含语义信息,有时从类名便可看出。
  2. 异常作为一个类,有自己的成员,可以传递足够的信息。
  3. 函数的返回值可以忽略,异常不可以忽略,可以使程序更加健壮。

三、基本语法

#include<iostream>
using namespace std; //异常基本语法 int divide(int x ,int y){
if (y == 0){
throw y; //抛异常
}
return x / y;
}
void test01(){ //试着去捕获异常
try{
divide(10, 0);
}
catch (int e){ //异常时根据类型进行匹配
cout << "除数为" << e << "!" << endl;
}
} void CallDivide(int x,int y){
divide(x, y);
}
//a() -> b() - >c() -> d(),d()中的异常一层层向上抛到terminate的标准库函数,直到处理为止 void test02(){
try{
CallDivide(10,0);
}
catch (int e){
cout << "除数为" << e << endl;
}
} //C++异常机制跨函数
//异常必须处理,如果异常抛到顶层还没有处理,程序便会挂掉。
int main(){ //test01();
test02();
}

四、栈解旋

异常被抛出后,从进入try块起,到异常被抛前,这期间在栈上构造的所有对象,都会被自动析构,析构的顺序与构造的顺序相反,这一过程即为栈解旋

构造函数没有返回类型,无法通过返回值来报告运行状态,所以通过异常机制来解决构造函数的出错问题。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std; class Person{
public:
Person(){
cout << "对象构建!" << endl;
}
~Person(){
cout << "对象析构!" << endl;
}
}; int divide(int x,int y){
Person p1, p2;
if (y == 0){
throw y;
}
return x / y;
} void test01(){ try{
divide(10,0);//栈解旋
}
catch (int e){
cout << "异常捕获!" << endl;
}
} int main(void)
{
test01();
return 0;
}
/*
结果:
对象构建!
对象构建!
对象析构!
对象析构!
异常捕获!
*/

五、异常接口声明

  1. 为了加强程序的可读性,可以在函数声明中列出可能抛出的所有异常类型,例如:

    void func() throw (A, B, C , D); //这个函数func()能够且只能抛出类型A B C D及其子类型的异常。
  2. 如果在函数声明中没有包含异常接口声明,则次函数可以抛掷任何类型的异常,例如:

    void func();
  3. 一个不抛掷任何类型异常的函数可以声明为:

    void func() throw();
  4. 如果一个函数抛出了它的异常接口声明所不允许抛出的异常,unexpected函数会被调用,该函数默认行为调用terminate函数中止程序
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std; //这个函数只能抛出int float char三种类型异常,抛出其他的就报错
void func() throw(int,float,char){
throw "abc";
} //不能抛出任何异常
void func02() throw(){
throw -1;
} //可以抛出任何类型异常
void func03(){
} int main(void)
{
try{
func();
}
catch (char* str){
cout << str << endl;
}
catch (int e){
cout << "异常!" << endl;
}
catch (...){ //捕获所有异常
cout << "未知类型异常!" << endl;
}
return 0;
} //结果: 未知类型异常!

六、异常对象的内存模型

throw的异常是有类型的,可以是数字、字符串、类对象,catch需严格匹配异常类型。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std; void func01(){
throw 1; //抛出int类型异常
} void func02(){
throw "exception";
} class MyException{
public:
MyException(const char* str){
error = new char[strlen(str)+1];
strcpy(error, str);
} MyException(const MyException& ex){
this->error = new char[strlen(ex.error) + 1];
strcpy(this->error,ex.error);
}
MyException& operator=(const MyException& ex){
if (this->error != NULL){
delete[] this->error;
this->error = NULL;
}
this->error = new char[strlen(ex.error) + 1];
strcpy(this->error, ex.error);
} void what(){
cout << error << endl;
}
~MyException(){
if (error != NULL){
delete[] error;
}
}
public:
char* error;
}; void fun03(){
throw MyException("我刚写异常!");
} void test01(){
try{
func01();
}
catch (int e){
cout << "int 异常捕获!" << endl;
}
//----------------------------------
try{
func02();
}
catch (const char* e){
cout << "const char* 异常捕获!" << endl;
}
//----------------------------------
try{
fun03();
}
catch (MyException e){
e.what();
}
}
int main(void){
test01();
return 0;
}
/*
int 异常捕获!
const char* 异常捕获!
我刚写异常!
*/

七、异常对象的生命周期

  1. catch里可以用普通类型元素,引用,指针去接
  2. 普通元素去接,异常对象catch处理完之后就析构
  3. 引用的话,不用调用拷贝构造,异常对象catch处理完之后就析构
  4. 指针接,throw的时候必须用new才能接的到,catch里必须要delete
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std; class MyException {
public:
MyException() {
cout << "构造函数!" << endl;
}
MyException(const MyException& ex) {
cout << "拷贝构造!" << endl;
}
~MyException() {
cout << "析构函数!" << endl;
}
};
void func() {
//throw &(MyException()); //创建匿名对象,调用构造
//throw new MyException();//用指针接
throw MyException();
}
void test01();
int main(void) {
test01();
return 0;
} /*
void test01();{
try {
func();
}
catch (MyException e) {
cout << "异常捕获!" << endl;
}
}
普通类型去接,结果为:
构造函数!
拷贝构造!
异常捕获!
析构函数!
析构函数!
*/ /*
void test01();{
try {
func();
}
catch (MyException& e) {
cout << "异常捕获!" << endl;
}
}
引用去接,结果为:
构造函数!
异常捕获!
析构函数!
*/
/*
void test01();{
try {
func();
}
catch (MyException* e) {
cout << "异常捕获!" << endl;
detele e;
}
}
指针去接,结果为:
构造函数!
异常捕获!
析构函数!
*/

C++ 异常机制(上)的更多相关文章

  1. Atitit 异常机制与异常处理的原理与概论

    Atitit 异常机制与异常处理的原理与概论 1. 异常vs 返回码1 1.1. 返回码模式的处理 (瀑布if 跳到失败1 1.2. 终止模式  vs 恢复模式(asp2 1.3. 异常机制的设计原理 ...

  2. C++ 异常机制分析

    C++异常机制概述 异常处理是C++的一项语言机制,用于在程序中处理异常事件.异常事件在C++中表示为异常对象.异常事件发生时,程序使用throw关键字抛出异常表达式,抛出点称为异常出现点,由操作系统 ...

  3. 【转载】C++异常机制的学习

    参考了这篇文章:http://blog.chinaunix.net/uid-24517549-id-4079174.html 关于线程 进程和线程的概念相信各位看官早已耳熟能详.在这里,我只想带大家回 ...

  4. Java异常机制

    Java异常分类 异常表明程序运行发生了意外,导致正常流程发生错误,例如数学上的除0,打开一个文件但此文件实际不存在,用户输入非法的参数等.在C语言中我们处理这类事件一般是将其与代码正常的流程放在一起 ...

  5. 黑马程序员——【Java基础】——面向对象(二)异常机制、包(Package)

    ---------- android培训.java培训.期待与您交流! ---------- 一.异常机制 (一)异常概述 1.异常:就是程序在运行时出现不正常情况. 2.异常类:程序在运行时,出现的 ...

  6. C 几种异常机制简单讲述

    引言 这是关于C中如何使用异常机制的讨论.顺带讲一讲C中魔法函数的setjmp内部机制.通过它实现高级的异常try...catch. 允许我先扯一段面试题. 对于计算机面试题. 算法题等.觉得还是有意 ...

  7. C++异常机制知识点

     在这里总结一下,C++中的异常机制,以及如何使用异常的知识点 C++中处理异常的过程是这样的:在执行程序发生异常,可以不在本函数中处理,而是抛出一个错误信息,把它传递给上一级的函数来解决,上一级解决 ...

  8. [转载]C++异常机制的实现方式和开销分析

    原文章网址:http://baiy.cn/doc/cpp/inside_exception.htm C++异常机制的实现方式和开销分析 白杨 http://baiy.cn 在我几年前开始写<C+ ...

  9. C++异常机制的实现方式和开销分析

    C++异常机制的实现方式和开销分析 白杨 http://baiy.cn http://baiy.cn/doc/cpp/inside_exception.htm 在我几年前开始写<C++编码规范与 ...

随机推荐

  1. JavaScript:记录一些字符串和数组常用的方法

    字符串: 字符串的方法:注意:都不会改变原来的字符串,返回值为新的字符串.如果(1,2),一般是包含小标1,不包含下标2 str.charAt(i): 取str的第i+1个字符,类似数组的arr[i] ...

  2. uni-app全局属性和方法

    全局变量和全局方法是软件开发中常用的技术点! 实现方式大致分为: 1.vuex实现,值变动灵活 2.建立js文件,页面内引用 3.挂载vue实例后使用 4.小程序中的globalData 5.本地存储 ...

  3. 数据结构与算法——图(游戏中的自动寻路-A*算法)

    在复杂的 3D 游戏环境中如何能使非玩家控制角色准确实现自动寻路功能成为了 3D 游戏开 发技术中一大研究热点.其中 A*算法得到了大量的运用,A*算法较之传统的路径规划算法,实时性更高.灵活性更强, ...

  4. WPS PDF转Word工具

    WPS PDF转Word工具链接:https://pan.baidu.com/s/1Ijh5MSBWZtsXsm05_6yYvw 提取码:gufy  下载运行后会解压到"D:\Program ...

  5. DVWA各等级XSS

    xss原理及基本介绍 XSS,全称Cross Site Scripting,即跨站脚本攻击,某种意义上也是一种注入攻击,是指攻击者在页面中注入恶意的脚本代码,当受害者访问该页面时,恶意代码会在其浏览器 ...

  6. 设置定时任务用rman删除归档日志脚本

    之前使用数据库数据迁移过程中出现产生大量归档日志的情况(由于迁移的目标库是DG,必须开启归档). 为避免出现归档空间爆掉的情况,设置定时任务删除系统当前时间30分钟前的归档日志,脚本如下: cat d ...

  7. 轮廓检测论文解读 | Richer Convolutional Features for Edge Detection | CVPR | 2017

    有什么问题可以加作者微信讨论,cyx645016617 上千人的粉丝群已经成立,氛围超好.为大家提供一个遇到问题有可能得到答案的平台. 0 概述 论文名称:"Richer Convoluti ...

  8. 工具-绿色使用软件等-破解pycharm,idea等Jet brain出品软件(99.2.1)

    1.下载此文件链接:https://pan.baidu.com/s/12nbtgeWiD1xKMtPIr-S1-g密码:b66f 并将 JetbrainsCrack-3.1-release-enc.j ...

  9. 在Linux中要修改一个文件夹或文件的权限

    在Linux中要修改一个文件夹或文件的权限我们需要用到linux chmod命令来做,下面我写了几个简单的实例大家可参考一下. 语法如下: chmod [who] [+ | - | =] [mode] ...

  10. DRF终极封装ViewSet和Router附教程PDF源码

    在DRF官方教程的学习过程中,一个很明显的感受是框架在不断地进行封装,我们自己写框架/工具/脚本/平台也可以模仿模仿,先完成底层代码,再做多层封装,让使用者很容易就上手操作.本文是教程的最后一篇,介绍 ...