子类实例的基类句柄。有没有一种优雅的方法可以在运行时获取子类类型?

发布于 2024-09-07 15:40:21 字数 589 浏览 3 评论 0原文

这就是我目前的做法:

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...)
}

有没有更“优雅”的方式来做到这一点?

按照我的方法,我必须为每个新的具体类添加一个新的 else if,这让我感觉自己就像 thedailywtf.com 上的示例之一。

This is how I do it currently:

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...)
}

Is there a more "elegant" way to do this?

With my approach, I have to add a new else if for every new Concrete Class, which makes me feel like one of the examples on thedailywtf.com.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

永不分离 2024-09-14 15:40:21

好吧,您可以做的一件简单的事情就是比较直接类型而不是使用字符串和类型名称:

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();

并且将为您调用适当的方法...

Well, one simple thing you could do to make this more elegant would be to compare the types directly instead of using strings and type names:

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...)
}

However, this has quite a bit of "code smell" to it. Typically, the entire point of using abstract classes is to allow for polymorphism - if you can make DoOtherStuff a virtual function on each type, you could just do:

base->DoOtherStuff();

And the appropriate method will get called for you...

逆蝶 2024-09-14 15:40:21

如果您的设计将有关 ConcreteClass1 特殊之处的所有知识限制在 ConcreteClass1 内,那就更优雅了。您是否可以在基类中拥有一个 Process() 函数,每个函数都从基类继承,并让它执行您的 if 主体将执行的任何操作,包括调用 DoOtherStuff(this)DoOtherStuff(this)代码>?这将有更好的封装,并且当您添加更多类时,您不会更改调用代码,因为它只是调用 base->Process() 并依赖于多态性。

It is more elegant if your design confines all the knowledge about what makes a ConcreteClass1 special inside ConcreteClass1. Could you have a Process() function in the base class that they each inherit from the base, and have it just do whatever your if bodies would do, including calling DoOtherStuff(this) ? That would have better encapsulation, and when you added more classes you wouldn't change your calling code, because it would just be calling base->Process() and relying on polymorphism.

说好的呢 2024-09-14 15:40:21

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

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

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

A better design than if statements, I find, is to use a dispatch table -- essentially a Dictionary from 'type' to function pointer / delegate. If the child class is responsible for registering itself to the table, then your dispatch function is simply something like :

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

and to add a new dispatch, it just needs to register itself in the table - no code updating required. This avoids maintaining the 'if' aggregate, and if you ever need to call more than one function you can make your dispatch table map to a more complex type.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文