何时/为什么要使用虚拟析构函数?
遵循 Herb Sutters指南:
基类析构函数应该是公共的和虚拟的,或者是受保护的和非虚拟的
这是否可以归类为未定义的行为(我们知道 ~D() 肯定不会被调用)?
根据标准,它是未定义的行为,这通常会导致未调用派生类析构函数并导致内存泄漏,但推测未定义行为的后效应是无关紧要的,因为标准在这方面不保证任何事情.
C++03 标准:5.3.5 删除
5.3.5/1:
delete-expression 运算符破坏由 new-expression 创建的最派生对象 (1.8) 或数组。
删除表达式
:::opt delete cast-expression
::opt delete [] cast-expression
5.3.5/3:
在第一种选择(删除对象)中,如果操作数的静态类型与其动态类型不同,则静态类型应为操作数动态类型的基类,并且静态类型应具有虚拟析构函数或行为未定义. 在第二种选择(删除数组)中,如果要删除的对象的动态类型与其静态类型不同,则行为未定义。73)
如果~D()
是空的怎么办。它会以任何方式影响代码吗?
根据标准,它仍然是未定义的行为,派生类析构函数为空可能只会使您的程序正常工作,但这又是特定实现的实现定义方面,从技术上讲,它仍然是未定义的行为。
请注意,这里没有保证不将派生类析构函数设为虚拟不会导致调用派生类析构函数,并且这个假设是不正确的。根据标准,一旦您在未定义行为领域越界,所有赌注都将取消。
请注意他的标准对未定义行为的规定。
C++03 标准:1.3.12 未定义行为 [defns.undefined]
行为,例如在使用错误程序结构或错误数据时可能出现的行为,本国际标准对此没有要求。当本国际标准省略对任何明确的行为定义的描述时,也可能会出现未定义的行为。[注意:允许的未定义行为范围从完全忽略具有不可预测结果的情况,到在翻译或程序执行期间以环境特征的记录方式表现(有或没有发出诊断消息),到终止翻译或执行(发出诊断消息)。许多错误的程序结构不会产生未定义的行为;他们需要被诊断出来。]
如果只有派生的析构函数不会被调用,则由上面引用中的粗体文本控制,这显然对每个实现都是开放的。