effective C++ 读书笔记 条款08「建议收藏」

effective C++ 读书笔记 条款08

大家好,又见面了,我是全栈君。

条款08  别让异常逃离析构函数:

假设在析构函数其中发生了异常,程序可能会过早结束或者导致不明白行为(异常从析构函数传播出去)

 

看代码:

#include <iostream>
using namespace std;


class DBConnection
{
public:


	void close()
	{
			int i = 3;
			int j = 0;
			int k = i/j;
			printf("%d\n",k);
	}
};

class DBConn
{
public:
	DBConn()
	{

	}

	/*
	~DBConn()
	{
			db.close();
	}
	*/



	//解决的方法1:强迫结束程序
	
	~DBConn()
	{
		try
		{
			db.close();
		}
		catch(...)
		{
			abort();//假设一个程序遭遇一个“于析构期间发生的错误”后无法继续同意,强迫结束是个合理的选择。用abort阻止异常从析构函数传播出去
		}
	}
	


	//解决的方法2:吞下异常
	/*
	~DBConn()
	{
		try
		{
			db.close();
		}
		catch (...)
		{
			//制作运转记录,记下对close的调用失败
		}
	
	}
	*/
private:
	DBConnection db;
};


int main()
{
	DBConn dbc;
	//dbc对象销毁时会自己主动调用DBConnection的close函数;仅仅要调用close成功,一切美好,可是假设该调用出现异常。DBConn析构函数
	//会传播该异常。也就是同意它离开这个析构函数。

会造成问题。

return 0;}/*採用本来的析构函数:执行程序。提示一个程序已经停止工作(感觉这里编译器优化到解决方式1了,自己主动做了处理),假设不停止工作。也出现了不明白行为。

採用解决方式1:执行程序,提示一个debug error,终止程序。採用解决方式2:执行程序,程序执行通过。可是也不会打印k的值*/

上面的解决方式1和2。都导致对close抛出的异常无法处理:

最佳办法就是DBConn自己又一次设计一个close接口,使得程序猿能够自己调用:

#include <iostream>
using namespace std;


class DBConnection
{
public:


	void close()
	{
			int i = 3;
			int j = 0;
			int k = i/j;
			printf("%d\n",k);
	}
};

class DBConn
{
public:
	DBConn()
	{

	}
	~DBConn()
	{
		if (!closed)
		{
			try  //关闭连接。假设客户不那么做的话
			{
				db.close()
			}
			catch(...)
			{
				//在这里结束程序或者吞下异常
			}
		}

	}

	void close()
	{
		db.close();
		closed = true;
	}


private:
	DBConnection db;
	bool closed;
};


int main()
{
	DBConn dbc;
	//dbc对象销毁时会自己主动调用DBConnection的close函数;仅仅要调用close成功,一切美好,可是假设该调用出现异常,DBConn析构函数
	//会传播该异常,也就是同意它离开这个析构函数。会造成问题。


	return 0;
}

/*

这种方法把调用close的责任从DBConn析构函数手上移动到DBConn客户手上(但DBConn析构函数仍含有一个“双保险”调用).

假设某个操作可能在失败时抛出异常。而又存在某种须要必须处理该异常,那么这个异常必须来自析构函数以外的某个函数
由于析构函数吐出异常,总会带来“过早结束程序”或者“发生不明白行为”的风险。

这里由客户自己调用close函数。假设发现异常,能够处理。总结: 1:析构函数绝对不要吐出异常,假设一个被析构函数调用的函数可能抛出异常,析构函数应该捕捉该异常,然后吞下它们(不传播)或结束程序 2:假设客户须要对某个操作函数执行期间抛出的异常做出反应,那么class应该提供一个普通函数(而非析构函数)执行该操作。*/

 

1:析构函数绝对不要吐出异常。假设一个被析构函数调用的函数可能抛出异常,析构函数应该捕捉该异常。然后吞下它们(不传播)或结束程序

2:假设客户须要对某个操作函数执行期间抛出的异常做出反应,那么class应该提供一个普通函数(而非析构函数)执行该操作。
 

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/115238.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • java技术介绍_Java技术汇总

    java技术介绍_Java技术汇总这篇文章总结了多年来使用Java的一些心得体会,主要是和一些Java基础知识点相关的,也希望能分享给刚刚入门的Java程序员和打算入Java开发这个行业的准新手们,希望可以给大家一些经验,能让大家更好学习和使用Java。这次介绍的主要内容是和J2SE相关的部分,经过这么多年的Java开发,以及结合平时面试Java开发者的一些经验,J2SE方面主要就是要掌握以下的一些内容。1.JVM相关(包括了…

  • SpringBoot 源码解读

    SpringBoot 源码解读Springboot之前出现的问题Spring框架需要进行大量的配置项目的依赖管理冲突为什么是SpringBootSpringBoot本身并不提供Spring框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新一代基于Spring框架的应用程序。也就是说,它并不是用来替代Spring的解决方案,而是和Spring框架紧密结合用于提升Spring开发者体验的工具。…

  • springboot整合rabbitmq,动态创建queue和监听queue

    springboot整合rabbitmq,动态创建queue和监听queue1、pom.xml添加如下依赖&lt;dependency&gt;&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;&lt;artifactId&gt;spring-boot-starter&lt;/artifactId&gt;&lt;/dependency&gt;…

  • Oracle sqlplus登录的三种方式[通俗易懂]

    sqlplus是oracle的一个客户端client,win7下有三个登录方式(图形版/DOS命令行版/IE版)1.图形版登陆sqlplus示例,具体如下①用户名:scott/tiger   口令:空   主机字符串:空或者orcl(创建oracle时的全局数据库名称)②用户名:scott   口令:tiger   主机字符串:空或者orcl(创建oracle时的全局数据库名称)③用户名:…

  • python优势有哪些?[通俗易懂]

    python优势有哪些?[通俗易懂]ol是英文orderedlist的缩写,翻译为中文是有序列表。有序列表是一种强调排列顺序的列表,使用标签定义,内部可以嵌套多个 标签。例如网页中常见的歌曲排行榜、游戏排行榜等都可以通过有序列表来定义。定义有序列表的基本语法格式如下: 列表项1 列表项2 列表项3 ……   在上面的语法中, 标签用于定义有序列表, 为具体的列表项,和无序列表类似,每对中 也至少应包含一对 。   在有序列表中,除了type属性之外,还可以为 定义start属..

  • 我的世界java手机_我的世界java手机版

    我的世界java手机_我的世界java手机版我的世界java手机版是一款非常好玩的模拟经营游戏,游戏非常的自由,你几乎可以在游戏中干任何事,你可以自己建造一个世界,或是制作一个像素版的动漫人物,你还可以探索这个世界,寻找资源,你还可以和好友一起在这里进行对抗,你还在等什么,赶快来体验吧!我的世界java手机版游戏特色没有华丽的画面,没有什么游戏特效但是它最大的优势就是在于它的游戏性玩家在一个完全开放的世界,可以完全按照自己的想法建造我的世界…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号