是否应该将输出操作放入析构函数中?

时间:2011-08-17 07:55:36

标签: c++ class

我有一个类在程序执行期间收集和处理一些数据,我们称之为dataCollectionInterface。当程序终止时(或者更确切地说:dataCollectionInterface对象超出范围),需要完成一些最终处理和(部分)收集数据的输出。

现在的问题是:我应该将这个最终处理和输出(到文件)放入dataCollectionInterface的析构函数中(或者从析构函数中调用它)吗?或者我应该提供需要主程序明确调用的公共成员例程(doFinalProcessing)?

将它放入析构函数会更方便(在调用doFinalProcessing之后无需担心数据调制的保护等),但是有缺点,例如关于处理输出操作中可能的异常?

4 个答案:

答案 0 :(得分:3)

你不应该 throwing any exceptions from the destructor ,如果你的操作可以抛出异常而你需要对它们进行异常处理,那么最好在公共函数中而不是析构函数中执行它。

但是,如果您可以在destrucotr中处理所有异常而不将它们从析构函数中删除,那么您也可以选择第一种机制,如果您能够可靠地执行此操作,我认为没有任何损害。

答案 1 :(得分:3)

析构函数不能失败。因此,你不应该进行任何操作 可能在析构函数中失败(并且输出可能失败);如果是这样你会怎么做 失败。

有例外,当操作与真正无关 程序的整体功能(例如,记录输出),或 当它是一个安全措施时(ofstream将关闭该文件 析构函数,忽略任何错误),或者当它是操作的一部分时 这将在以后“废止”:非承诺的转换可能会关闭 输出文件,例如,知道因为事务不是 提交后,该文件将被删除。但他们就是这样: 例外。

答案 2 :(得分:1)

我会提供:析构函数具有一些默认行为(捕获所有异常并且可能对可能的问题保持沉默)和具有扩展诊断的公共成员例程。使用什么方法取决于班级的用户。在内部,析构函数可以使用try / catch块调用例程,如果例程可能抛出的话。例程应该是幂等的(第二次调用应该什么都不做)

答案 3 :(得分:1)

其他人对于没有抛出的析构函数是正确的,但这并不意味着不要在析构函数中执行它。也不应该意味着不应该有诊断。但你绝对应该把它放在析构函数中。

首先,你应该把它放在析构函数中的原因不是立即方便,而是因为僵尸是邪恶的。已经完成其使用寿命但仍然存在意外遇到和使用的对象是开发人员的祸根。年轻的开发人员在他们不应该引起各种各样的问题时进来接触他们。复杂性爆炸,因为你现在必须检查你是否已经正确清理了东西。异常处理现在不是自动的,因为它将在析构函数中。你是否真的想在你使用该对象的任何地方编写try / catches只是因为不相关的东西可能会抛出而你必须正确地清理它?您是否想在该类的所有代码中编写“ifs”以确保它们不使用大多数死对象?

两阶段初始化或破坏是代码味道,您没有正确使用ctors / dtors。使用它们来自动化所有对象的生命周期(RAII),你将永远不会拥有僵尸带来的代码脆弱性。

那么,如果输出操作可能会抛出怎么办?

  • 在try / catch中使用可能的投掷电话。
  • 在对象的构造函数中,从用户处获取错误处理例程的可选函数回调。
  • 在dtor中,当发现异常时,调用回调(如果他们给你一个),你可以提供任何诊断
  • 在try / catch中包装回调调用,因为您不知道其他人会做什么
  • 如果回调引发则不做任何事 - 他们有机会

真的那么简单。即使你在dtors中有特殊的异常代码,也不要让僵尸漫游。相反,提供一种以抽象方式处理它的方法。当僵尸被释放时,一个特殊的清理特例总是比特殊情况的组合爆炸更好。