0

我在子类中覆盖了基类函数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 中删除了 virtual 并使用强制转换,调用了 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;
    }
    

m_objs:

CObArray m_objs;

对象存储为:

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

但是有人可以更详细地解释这一点吗?

4

3 回答 3

2

我不确定您如何进行调试。你说你可以看到 CSwitch 的一个成员变量。如果您的意思是您检查CSwitch* sw = (CSwitch*)obj;并看到这样的 var in 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,这是我能猜到的最好的)

于 2012-11-21T04:20:01.390 回答
1

因为即使您将 CDiagramEntity 对象强制转换为 CSwitch 对象,调用也是通过虚拟调度进行的。因此,如果 GetSelectedObject 返回的对象实际上不是 CSwitch,则调用 CDiagramEntity 的 ShowProperties。

为什么要将对象转换为 CSwitch?从设计的角度来看,这没有意义。您有一个多态对象,但您想将其视为其特殊派生之一。

于 2012-11-21T03:43:18.970 回答
1

因为ShowProperties()是一个virtual函数。

virtual机制启动时,函数绑定发生在运行时
如果ShowProperties()返回 的对象class CDiagramEntity,则CDiagramEntity::ShowProperties()无论static type调用指针的类型如何,都将被调用(此处sw)。

仅出于实验目的,删除virtual关键字并运行代码。您将获得预期的行为。但要注意可能的未定义行为。

于 2012-11-21T03:41:42.010 回答