我覆盖了子类中的基类函数ShowProperties
,但仍调用了基类函数。这是为什么?
类层次结构:
class CDiagramEntity : public CObject
{
public:
virtual void ShowProperties( CWnd* parent, BOOL show = TRUE );
}
class CNetworkSymbol : public CDiagramEntity
{
/*NO 'ShowProperties' Function*/
}
class CDeviceEntity : public CNetworkSymbol
{
/*NO 'ShowProperties' Function*/
}
class CSwitch : public CDeviceEntity
{
public:
virtual void ShowProperties( CWnd* parent, BOOL show = TRUE );
}
使用:
/*Use Here*/
{
CDiagramEntity* obj = GetSelectedObject();
if( obj )
{
CSwitch* sw = (CSwitch*)obj;
sw->ShowProperties( this );
/*calls CDiagramEntity's function, not CSwitch's function*/
}
}
PS:
如@ user1610015评论,如果我使用
CSwitch* sw = dynamic_cast<CSwitch*>(obj);
它返回NULL
。
正如@Andrian Sham所说,我遇到了问题的原因:
GetSelectedObject()--->finally calls--->
{
CDiagramEntity* result = NULL;
if ( index < m_objs.GetSize() && index >= 0 )
result = static_cast< CDiagramEntity* >( m_objs.GetAt( index ) );
/*m_objs is defined as: CObArray m_objs;*/
return result;
}
M_OBJS:
CObArray m_objs;
对象存储为:
...( CDiagramEntity* obj )
{
obj->SetParent( this );
m_objs.Add( obj );
SetModified( TRUE );
}
但有人可以更详细地解释一下吗?
答案 0 :(得分:2)
我不确定你是如何进行调试的。你说你可以看到CSwitch的成员变量。如果您的意思是检查CSwitch* sw = (CSwitch*)obj;
并在sw
中看到此类变量,那么您实际上是错误的。调试器只是“解释”sw
指向的内存块,因为它是一个CSwitch。这并不意味着它真的是一个CSwitch。
我只能想到一个案例。您是否将对象实例放在任何STL容器中并将其取出以将其作为选择项?
(我完全忘记了MFC,这只是一个例子)
vector<CDiagramEntity> entities; // note it is of type CDiagramEntity, not CDiagramEntity*
CSwitch aCSwitch;
entities.push_back(aCSwitch);
// later
SetItem("SomeValue", entities[i]);
您可能认为实体[i]应该返回CSwitch的实例,但事实并非如此。
(如果您非常确定所选项目应该是CSwitch,这是我能猜到的最好的)
答案 1 :(得分:1)
因为ShowProperties()
是 virtual
功能。
当virtual
机制启动时,功能绑定发生在运行时
如果ShowProperties()
正在返回class CDiagramEntity
的对象,那么无论CDiagramEntity::ShowProperties()
类型的调用指针(此处为static type
),都会调用sw
。
仅出于实验目的,请移除virtual
关键字并运行代码。您将获得预期的行为。但要注意可能的未定义行为。
答案 2 :(得分:1)
因为即使您将CDiagramEntity对象强制转换为CSwitch对象,也会通过虚拟调度进行调用。因此,如果GetSelectedObject返回的对象实际上不是CSwitch,则调用CDiagramEntity的ShowProperties。
为什么要将对象转换为CSwitch?从设计角度来看,它没有意义。您有一个多态对象,但您希望将其视为其专用派生之一。