为什么基类功能没有被覆盖?

时间:2012-11-21 03:34:15

标签: c++ class inheritance mfc override

我覆盖了子类中的基类函数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:

  1. 正如@iammilind建议的那样,我从CDiagramEntity中移除虚拟并使用强制转换,调用CSwitch的函数,并从它显示的属性(属性只能更改为创建CSwitch时显示的属性),我相当确定它是一个CSwitch。
  2. 如@ user1610015评论,如果我使用

    CSwitch* sw = dynamic_cast<CSwitch*>(obj);
    

    它返回NULL

  3. 正如@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;
    }
    
  4. M_OBJS:

    CObArray m_objs;
    

    对象存储为:

    ...( CDiagramEntity* obj )
    {
      obj->SetParent( this );
      m_objs.Add( obj );
      SetModified( TRUE );
    }
    

    但有人可以更详细地解释一下吗?

3 个答案:

答案 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?从设计角度来看,它没有意义。您有一个多态对象,但您希望将其视为其专用派生之一。