C++ 应该将输出操作放入析构函数吗?

C++ 应该将输出操作放入析构函数吗?,c++,class,C++,Class,我有一个类,它在程序执行期间收集和处理一些数据,我们称之为dataCollectionInterface。当程序终止时(或者更确切地说:一个dataCollectionInterface对象超出范围),需要对收集的数据进行一些最终处理和输出 现在的问题是:我是否应该将这个最终处理和输出(到文件)放入dataCollectionInterface的析构函数中(或者从析构函数中调用它)?或者我应该提供一个需要由主程序显式调用的公共成员例程(doFinalProcessing) 将其放入析构函数会方便

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

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


将其放入析构函数会方便得多(无需担心调用
doFinalProcessing
等后数据调制的保护措施),但是否存在缺点,例如在处理输出操作中可能出现的异常方面?

您不应该这样做,因此,如果您的操作可以引发异常,并且需要对异常进行处理,那么最好在公共函数中执行此操作,而不是在析构函数中执行此操作


尽管如此,如果您可以在析构函数本身中处理所有异常,而不将它们从析构函数中抛出,那么您也可以使用第一种机制,如果您能够可靠地这样做,我看不出有什么害处。

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

当操作与系统不相关时,也有例外 程序的总体功能(例如,记录输出),或 当它是一种保护措施时(
ofstream
将在 析构函数,忽略任何错误),或当它是操作的一部分时 随后将被“撤销”:未承诺的交易可能会关闭 输出文件,例如,知道因为事务不是 如果已提交,则稍后将删除该文件。但它们只是:
例外情况

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

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

首先,你应该把它放在析构函数中的原因不是为了方便,而是因为僵尸是邪恶的。已经完成其有用生命周期但仍然存在以供意外遇到和使用的对象是开发人员的祸根。年轻的开发人员在他们不应该引起各种问题的时候介入并接触他们。复杂性爆炸,因为你现在必须检查你是否正确地清理了东西。异常处理现在不是自动的,就像在析构函数中一样。你真的想在你使用对象的任何地方写try/catch吗?仅仅因为一些不相关的东西可能会抛出,你必须正确地清理它?是否要在该类的所有代码中编写“ifs”,以确保它们没有使用死气沉沉的对象

两阶段初始化或销毁是指您没有正确使用CTOR/DTOR的代码。使用它们来自动化对象的整个生命周期(RAII),您将永远不会有僵尸带来的代码脆弱性

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

  • 用try/catch来概括你对可能抛出的呼叫的使用
  • 在对象的构造函数中,使用可选函数回调用户的错误处理例程
  • 在dtor中,当捕获到异常时,使用您可以提供的任何诊断调用回调(如果他们给了您一个回调)
  • 在try/catch中包装回调调用,因为您不知道其他人会做什么
  • 如果回调抛出,什么也不要做——他们有机会

就这么简单。永远不要让僵尸漫游,即使你在DTOR中有特殊的异常代码。相反,提供一种以抽象方式处理该问题的方法。当僵尸被释放时,一个清理的特例总比一个特例的组合爆炸要好。

你的最后一段已经是你的答案了。您拥有判断哪种机制最适合的最佳信息。找出是否有可能处理析构函数中的所有异常,否则,请使用其他解决方案。好的,我可以猜到parashift常见问题解答中有一些内容。谢谢你指出这一点。通过在析构函数内部处理异常,您的意思是我应该将
try
-
catch
块放在析构函数内部,并直接从这个catch块中写出任何相关的错误消息“blablabla中失败”等?@jantitor048:Yup。但是您需要绝对确保没有任何异常逃逸您的catch处理程序。只需确保在catch块中输出错误消息也不能抛出!