C++异常处理 - 栈解旋,异常接口声明,异常类型和异常变量的生命周期
栈解旋(unwinding)
异常被抛出后,从进入try块起,到异常被抛掷前,这期间在栈上的构造的所有对象,都会被自动析构。析构的顺序与构造的顺序相反。这一过程称为栈的解旋(unwinding)。
demo 1
- #include <iostream>
- #include <cstdio>
- using namespace std;
- class MyException {};
- class Test
- {
- public:
- Test(int a = 0, int b = 0)
- {
- this->a = a;
- this->b = b;
- cout << "Test 构造函数执行" << "a:" << a << " b: " << b << endl;
- }
- void printT()
- {
- cout << "a:" << a << " b: " << b << endl;
- }
- ~Test()
- {
- cout << "Test 析构函数执行" << "a:" << a << " b: " << b << endl;
- }
- private:
- int a;
- int b;
- };
- void myFunc() throw (MyException)
- {
- Test t1;
- Test t2;
- cout << "定义了两个栈变量,异常抛出后测试栈变量的如何被析构" << endl;
- throw MyException();
- }
- int main()
- {
- //异常被抛出后,从进入try块起,到异常被抛掷前,这期间在栈上的构造的所有对象,
- //都会被自动析构。析构的顺序与构造的顺序相反。
- //这一过程称为栈的解旋(unwinding)
- try
- {
- myFunc();
- }
- //catch(MyException &e) //这里不能访问异常对象
- catch (MyException) //这里不能访问异常对象
- {
- cout << "接收到MyException类型异常" << endl;
- }
- catch (...)
- {
- cout << "未知类型异常" << endl;
- }
- 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函数中止程序。
传统处理错误
- #include <iostream>
- #include <cstdio>
- using namespace std;
- // 传统的错误处理机制
- int myStrcpy(char *to, char *from)
- {
- if (from == NULL) {
- return 1;
- }
- if (to == NULL) {
- return 2;
- }
- // copy时的场景检查
- if (*from == 'a') {
- return 3; // copy时错误
- }
- while (*from != '\0') {
- *to = *from;
- to++;
- from++;
- }
- *to = '\0';
- return 0;
- }
- int main()
- {
- int ret = 0;
- char buf1[] = "zbcdefg";
- char buf2[1024] = { 0 };
- ret = myStrcpy(buf2, buf1);
- if (ret != 0) {
- switch (ret) {
- case 1:
- cout << "源buf出错!\n";
- break;
- case 2:
- cout << "目的buf出错!\n";
- break;
- case 3:
- cout << "copy过程出错!\n";
- break;
- default:
- cout << "未知错误!\n";
- break;
- }
- }
- cout << "buf2:\n" << buf2;
- cout << endl;
- return 0;
- }
throw char*
- #include <iostream>
- #include <cstdio>
- using namespace std;
- // throw char *
- void myStrcpy(char *to, char *from)
- {
- if (from == NULL) {
- throw "源buf出错";
- }
- if (to == NULL) {
- throw "目的buf出错";
- }
- // copy时的场景检查
- if (*from == 'a') {
- throw "copy过程出错"; // copy时错误
- }
- while (*from != '\0') {
- *to = *from;
- to++;
- from++;
- }
- *to = '\0';
- return;
- }
- int main()
- {
- int ret = 0;
- char buf1[] = "abcdefg";
- char buf2[1024] = { 0 };
- try
- {
- myStrcpy(buf2, buf1);
- }
- catch (int e) // e可以写可以不写
- {
- cout << e << "int类型异常" << endl;
- }
- catch (char *e)
- {
- cout << "char* 类型异常" << endl;
- }
- catch (...)
- {
- };
- cout << endl;
- return 0;
- }
throw 类对象
- #include <iostream>
- #include <cstdio>
- using namespace std;
- class BadSrcType {};
- class BadDestType {};
- class BadProcessType
- {
- public:
- BadProcessType()
- {
- cout << "BadProcessType构造函数do \n";
- }
- BadProcessType(const BadProcessType &obj)
- {
- cout << "BadProcessType copy构造函数do \n";
- }
- ~BadProcessType()
- {
- cout << "BadProcessType析构函数do \n";
- }
- };
- //throw 类对象 类型异常
- void my_strcpy3(char *to, char *from)
- {
- if (from == NULL)
- {
- throw BadSrcType();
- }
- if (to == NULL)
- {
- throw BadDestType();
- }
- //copy是的 场景检查
- if (*from == 'a')
- {
- printf("开始 BadProcessType类型异常 \n");
- throw BadProcessType(); //会不会产生一个匿名对象?
- }
- if (*from == 'b')
- {
- throw &(BadProcessType()); //会不会产生一个匿名对象?
- }
- if (*from == 'c')
- {
- throw new BadProcessType; //会不会产生一个匿名对象?
- }
- while (*from != '\0')
- {
- *to = *from;
- to++;
- from++;
- }
- *to = '\0';
- }
- int main()
- {
- int ret = 0;
- char buf1[] = "cbbcdefg";
- char buf2[1024] = { 0 };
- try
- {
- //my_strcpy1(buf2, buf1);
- //my_strcpy2(buf2, buf1);
- my_strcpy3(buf2, buf1);
- }
- catch (int e) //e可以写 也可以不写
- {
- cout << e << " int类型异常" << endl;
- }
- catch (char *e)
- {
- cout << e << " char* 类型异常" << endl;
- }
- //---
- catch (BadSrcType e)
- {
- cout << " BadSrcType 类型异常" << endl;
- }
- catch (BadDestType e)
- {
- cout << " BadDestType 类型异常" << endl;
- }
- //结论1: 如果 接受异常的时候 使用一个异常变量,则copy构造异常变量.
- /*
- catch( BadProcessType e) //是把匿名对象copy给e 还是e还是那个匿名对象
- {
- cout << " BadProcessType 类型异常" << endl;
- }
- */
- /*结论2: 使用引用的话 会使用throw时候的那个对象
- catch( BadProcessType &e) //是把匿名对象copy给e 还是e还是那个匿名对象
- {
- cout << " BadProcessType 类型异常" << endl;
- }
- */
- //结论3: 指针可以和引用/元素写在一块 但是引用和元素不能写在一块
- catch (BadProcessType *e) //是把匿名对象copy给e 还是e还是那个匿名对象
- {
- cout << " BadProcessType 类型异常" << endl;
- delete e;
- }
- //结论4: 类对象时, 使用引用比较合适
- // --
- catch (...)
- {
- cout << "未知 类型异常" << endl;
- }
- return 0;
- }
C++异常处理 - 栈解旋,异常接口声明,异常类型和异常变量的生命周期的更多相关文章
- C++基础 (10) 第十天 C++中类型转换 异常 栈解旋 io操作
1之前内容的回顾 C语言中的类型转换(int)a 强转可读性太差了 C++把()拆分成了四种转换方式 static_cast static_cast在编译器编译阶段就进行转换了 2.dynamic_ ...
- 牛客网Java刷题知识点之什么是异常、异常处理的原理是什么、为什么要使用异常、异常体系、运行时异常、普通异常、自定义异常、异常链
不多说,直接上干货! 在这个世界不可能存在完美的东西,不管完美的思维有多么缜密,细心,我们都不可能考虑所有的因素,这就是所谓的智者千虑必有一失.同样的道理,计算机的世界也是不完美的,异常情况随时都会发 ...
- C++异常之三 异常处理接口声明
异常处理接口声明 1 一般为了方便程序员阅读代码,提高程序的可读性,会将函数中的异常类型声明至函数头后方,不用一行一行的找抛出内容: 2 这里要注意一点,这属于C++的标准语法,但在VS中这个操作不被 ...
- JAVA之旅(十)——异常的概述,Try-Catch,异常声明Throws,多异常处理,自定义异常,Throw和Throws的区别
JAVA之旅(十)--异常的概述,Try-Catch,异常声明Throws,多异常处理,自定义异常,Throw和Throws的区别 不知不觉,JAVA之旅这个系列已经更新到第十篇了,感觉如梦如幻,时间 ...
- java异常处理 throw RuntimeException时不需要同时方法中声明抛出throws 异常等待调用者catch进行捕获 子父类异常问题
package com.swift.exception1; public class Demo_Exception { public static void main(String[] args) { ...
- “全栈2019”Java异常第十五章:异常链详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java异 ...
- “全栈2019”Java异常第十三章:访问异常堆栈跟踪信息
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java异 ...
- “全栈2019”Java异常第一章:什么是异常?
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java异 ...
- C++异常之七 标准库里的异常类
标准库里的异常类 C++标准提供了一组标准异常类,这些类以基类 Exception 开始,标准程序库抛出的所有异常,都派生于该基类,这些类构成如图所示的异常类的派生继承关系,该基类提供一个成员函数 w ...
随机推荐
- 深入理解DirectByteBuffer
介绍 最近在工作中使用到了DirectBuffer来进行临时数据的存放,由于使用的是堆外内存,省去了数据到内核的拷贝,因此效率比用ByteBuffer要高不少.之前看过许多介绍DirectBuffer ...
- “ML学分计划”说明书
计划的由来 我们是一群对机器学习感兴趣的小伙伴,对于神奇的机器学习经常有"一探究竟"的冲动,却因为孤身一人学习的寂寞.亦或繁忙考试工作之余的小小拖延症,而没有持续这份对知识的渴求和 ...
- Dynamics CRM2016 Web API之获取查找字段的text及选项集的text
本篇再来介绍个web api的功能,关于lookup的text这里只是略带,因为有expand,现有的web api就能实现,主要提的是选项集的text,我们通过基本的查询api查出来的字段值只带有v ...
- Appium移动自动化框架初探
作者:cryanimal QQ:164166060 本文简要介绍了appnium自动化框架的架构.加载流程.支持语言.相关配置,以及元素定位工具等. 官方网站: http://appium.io Ap ...
- FORM执行查询的各种方法
一.FORM调用FORM后执行查询 1.打开 APPSTAND.fmb,把 Object Groups 下的 QUERY_FIND 对象组拖动到自己的 form 中的 Object Groups ...
- FFmpeg的H.264解码器源代码简单分析:概述
===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...
- 5、Android Service测试
如果你在应用中使用了Service,你应该来测试这个Service来确保它正常工作.你可以创建仪表测试来验证Service的行为是否正确:比如,service保存和返回有效的数值并正常的处理数据. A ...
- Spark技术内幕:究竟什么是RDD
RDD是Spark最基本,也是最根本的数据抽象.http://www.cs.berkeley.edu/~matei/papers/2012/nsdi_spark.pdf 是关于RDD的论文.如果觉得英 ...
- Objc中为何某些类的属性要设置为copy而不是strong?
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 不知道大家是否注意,我们再使用一些第三方类的时候大多数情况下对 ...
- 04 Spinner 列表选中
<span style="font-size:18px;"> <?xml version="1.0" encoding="utf-8 ...