这样安全吗?
class Derived: public PublicBase, private PrivateBase
{
...
~Derived()
{
FunctionCall();
}
virtual void FunctionCall()
{
PrivateBase::FunctionCall();
}
}
class PublicBase
{
virtual ~PublicBase(){};
virtual void FunctionCall() = 0;
}
class PrivateBase
{
virtual ~PrivateBase(){};
virtual void FunctionCall()
{
....
}
}
PublicBase* ptrBase = new Derived();
delete ptrBase;
Run Code Online (Sandbox Code Playgroud)
此代码有时会在错误的地址中使用IP.
对于每个人来说,在构造函数上调用虚函数并不是一个好主意.
来自像http://www.artima.com/cppsource/nevercall.html这样的文章我明白析构函数也是一个不太适合调用虚函数的地方.
我的问题是"这是真的吗?" 我已经测试过VS2010和VS2005并且调用了PrivateBase :: FunctionCall.未定义的行为?
Dav*_*eas 66
我将反对这里的流程......但首先,我必须假设你的PublicBase
析构函数是虚拟的,否则Derived
析构函数永远不会被调用.
从构造函数/析构函数调用虚函数通常不是一个好主意
原因是在这两个操作期间动态调度很奇怪.对象的实际类型在构造期间更改,并且在销毁期间再次更改.当一个析构函数被执行时,该对象就是那种类型,而不是从它派生的类型.动态调度始终有效,但虚拟函数的最终覆盖将根据您在层次结构中的位置而更改.
也就是说,您永远不应期望在构造函数/析构函数中对虚函数的调用以从正在执行的构造函数/析构函数的类型派生的任何类型执行.
但
在您的特定情况下,最终的覆盖(至少在层次结构的这一部分)高于您的级别.而且,您根本不使用动态调度.该呼叫PrivateBase::FunctionCall();
是静态解析的,实际上相当于对任何非虚函数的调用.函数是否为虚拟的事实不会影响此调用.
所以是的,你正在做的很好,虽然你会被迫在代码审查中解释这一点,因为大多数人都学习规则的咒语而不是理由.
Mik*_*our 21
这样安全吗?
是.从构造函数或析构函数调用虚函数调度该函数,就好像该对象的动态类型是当前正在构造或销毁的那样.在这种情况下,它是从析构函数调用的Derived
,所以它被派遣到Derived::FunctionCall
(在你的情况下,PrivateBase::FunctionCall
非虚拟调用).所有这一切都很明确.
从构造函数或析构函数调用虚函数是"不是一个好主意"有三个原因: