子类实例的基类句柄。是否有一种优雅的方式来在运行时获取子类类型?

时间:2010-06-30 15:46:58

标签: .net class c++-cli

这就是我目前的做法:

ref class Base abstract {};
ref class ConcreteClass1 : public Base {};
ref class ConcreteClass2 : public Base {};
(...and even more...)

void DoStuff(Base ^base)
{
   System::Type ^type = base->GetType();
   System::String ^name = type->Name;

   if(name == "ConcreteClass1")
          DoOtherStuff((ConcreteClass1 ^) base);
   else if(name == "ConcreteClass2")
          DoOtherStuff((ConcreteClass2 ^) base);
   (...and even more...)
}

有更“优雅”的方法吗?

根据我的方法,我必须为每个新的Concrete Class添加一个新的else,这让我感觉像是thedailywtf.com上的一个例子。

3 个答案:

答案 0 :(得分:2)

嗯,你可以做的一件简单的事情就是compare the types directly而不是使用字符串和类型名称:

void DoStuff(Base ^base)
{
   System::Type ^type = base->GetType();

   if(type == ConcreteClass1::typeid)
          DoOtherStuff((ConcreteClass1 ^) base);
   else if(type == ConcreteClass2::typeid)
          DoOtherStuff((ConcreteClass2 ^) base);
   (...and even more...)
}

但是,它有相当多的“代码味道”。通常,使用抽象类的整个要点是允许多态 - 如果你可以在每种类型上使DoOtherStuff成为虚函数,你可以这样做:

base->DoOtherStuff();

并且会为你调用适当的方法......

答案 1 :(得分:1)

如果你的设计限制了ConcreteClass1内部ConcreteClass1特殊内容的所有知识,那就更优雅了。你可以在基类中有一个Process()函数,它们都是从基类继承的,并且它只是做你想做的任何事情,包括调用DoOtherStuff(this)?那将有更好的封装,当你添加更多的类时,你不会改变你的调用代码,因为它只是调用base->Process()并依赖于多态。

答案 2 :(得分:1)

我发现,比if语句更好的设计是使用调度表 - 本质上是从'type'到函数指针/委托的字典。如果子类负责将自己注册到表中,那么您的调度函数就像是:

void DoStuff(Base ^base)
{
    System::Type ^type = base->GetType();
    m_DispatchTable[type](base);
}

并添加新的调度,它只需要在表中注册自己 - 无需更新代码。这样可以避免维护“if”聚合,如果您需要调用多个函数,可以将调度表映射为更复杂的类型。