当基类指针传递参数时,检查孩子的类型

checking type of child when argument is passed by base class pointer

本文关键字:检查 孩子 类型 参数 基类 指针      更新时间:2023-10-16

我有一个基础B及其2个衍生(D1D2)类,看起来像

struct B
{
   virtual B* DoSomething()=0;
};
struct D1:public B
{
   B* DoSomething()
   {
      // D1 does something
      return pD1;
   }
};
struct D2:public B
{
   B* DoSomething()
   {
     // D2 does something
     return pD2;
   }
};

现在我有一个函数

void Init(B*pB)
{
   if(pB is D1)
   {
      D1* pD1=down_cast(pB);
      pD1->MethodD1();
   }
   else if(pB is D2)
   {
      D2* pD2=down_cast(pB);
      pD2->MethodD2();
   }
   else
   {
      //do something else
   }
}

我不想在Init()中检查类型,但不知道我可以做什么。

真的应该做

struct B
{
   virtual void Init();
   virtual B* DoSomething()=0;
};
struct D1:public B
{
   B* DoSomething()
   {
      // D1 does something
      return pD1;
   }
   void Init()
   {
      MethodD1();
   }
};

struct D2:public B
{
   B* DoSomething()
   {
      // D2 does something
      return pD2;
   }
   void Init()
   {
      MethodD2();
   }
};

和您的主代码

void Init(B*pB)
{
   pB->Init();
}

那就是封装,继承,虚拟方法等的全部点。

这是您的 Init()方法不在伪代码中:

void Init(B*pB)
{
   if(D1 *pD1 = dynamic_cast<D1*>(pB))
   {
      pD1->MethodD1();
   }
   else if(D2 *pD2 = dynamic_cast<D2*>(pB))
   {
      pD2->MethodD2();
   }
   else
   {
      //do something else
   }
}

您可以看到Dynamic_cast返回nullptr如果派生类的类型不是您要铸造的类。

您也可以使用引用来执行此操作,在这种情况下,Dynamic_cast会返回一个例外,如果类型不是您要铸造的类型,因此,由于异常处理不是免费的,因此最好将指针用于动态铸造目的。请注意,这是运行时检查,而不是编译时间检查。