何时/为什么我应该使用虚拟析构函数?
关注香草Sutters guideline:
的基类的析构函数应该是公开和虚拟,或保护和非虚
是否可以将其归类为未定义的行为(我们都知道那〜D()不会被肯定地调用)?
它是未定义按照标准的行为,这通常会导致Derived类析构函数未被调用并导致内存泄漏,但是在未定义行为的效率之后进行推测是没有意义的,因为标准没有保持这方面的任何事情。
C++ 03标准:5.3.5删除
5.3.5/1:
的delete表达式运算符破坏创建的最派生对象(1.8)或阵列由一个新的表达。
删除表达式:
::选择删除铸表达
::选择删除[]铸表达
5.3.5/3:
在第一如果操作数的静态类型与其动态类型不同,静态类型应该是操作数动态类型的基类,并且静态类型应该具有虚拟析构函数或行为未定义。在第二替代(删除数组)如果动态类型的对象从它的静态类型删除不同的,那么行为是undefined.73)
如果什么~D()
是空的。它会以任何方式影响代码?
尽管它是未定义的行为按照标准,派生类析构函数为空可能只是让你的程序正常工作,但这又是一个特定实现的实现定义的方面,从技术上讲,它仍然是一个未定义的行为。
请注意,没有gaurantee在这里没有让派生类析构函数虚拟只是不会导致调用派生类析构函数,这种假设是不正确的。根据标准,所有投注都会在未定义的行为区域中越过。
请注意他标准中关于未定义行为的说法。
的C++ 03标准:1.3.12未定义的行为[defns.undefined]
行为,如在使用时的错误的程序构建体或错误的数据,为此,本国际的可能出现标准没有要求。本国际标准忽略对行为的任何明确定义的描述时,也可能会出现未定义的行为。 [注意:允许的未定义的行为范围从完全忽略具有不可预知的结果的情况到在以翻译或程序执行期间以文档化的方式表现的环境特征(发布或不发布诊断消息),终止翻译或执行(通过发布诊断消息)。许多错误的程序结构不会产生未定义的行为;他们需要被诊断。]
如果只有派生的析构函数不会被调用,则由上面引用中的粗体文本控制,这对每个实现都是明确的。
我经常想到要问同样的事情。 (1)B没有虚拟方法,(2)B有一个虚拟方法,但是是一个非虚拟析构函数,(3)。 B有一个虚拟析构函数。显然,只有后者是明确定义的:http://stackoverflow.com/questions/2065938/virtual-destructor – 2011-12-22 03:56:48
这是我的牙齿:) – mlvljr 2014-10-21 16:07:10