【问题标题】:(C++) Finding the child type of a base type pointer [closed](C++)查找基类型指针的子类型[关闭]
【发布时间】:2017-11-27 11:12:56
【问题描述】:

我有一个class Base 和 4 个类 ABCD,每个类都派生自 Base。我将指针Base* 传递给一个函数。

我知道我可以使用dynamic_cast 来检查每个单独的子类型。为了找出该指针的类型,我必须使用 4 个不实用的 if 语句。

这可以通过其他更优雅的方式完成吗?

  • 或者我应该在每个子类中保存一个const int 变量来指示它的类型,以便简单地调用GetType()
  • 或者我应该专注于确保当我有一个存储时 - 例如库存和ABCD 是不同类型的项目 - 项目自己排序(这样当我有 4 个列表时,新项目会将自己放置在正确的列表中,而不是具有管理库存、检查项目类型然后将其放置在正确列表中的功能)?

【问题讨论】:

  • 你真的需要投吗?如果您提供虚函数,您可以通过指向基的指针对派生对象执行大多数操作。
  • 问题很常见。一直出现。通常人们在基类中放置一个枚举并创建一个成员来识别类型。这很糟糕,因为基类必须了解每个派生类型。这种情况更多地发生在数据对象中,然后是通用接口就足够的功能对象。示例:BaseResponse、CustomerResponse、CustomerFeedBackResponse...其中每个都有更多特定于该类型的数据成员。虽然我不知道更好的方法。我们在 C++ 中没有反射。也许其他人有更好的答案。
  • 您可以使用typeid 按派生类型进行索引。
  • @ChristopherPisz 有更好的方法。更好的方法是不要尝试将通用代码(使用接口和基类的代码)降低到特定的代码(处理具体类型的代码)。如果您已经编写了执行动态转换以执行特定类型的特定代码的代码,那么您应该不需要动态转换并且可以直接访问特定类型。如果你不能这样做,你就有架构问题。
  • @ChristopherPisz 顺便说一下,如果你给出了有限数量的基类,而不是枚举,你应该使用std::variant

标签: c++ inheritance types


【解决方案1】:

或者我应该在每个子类中保存一个 const int 变量来指示它的类型,以便简单地调用 GetType()?或者我应该专注于确保当我有一个存储时 - 例如库存和 A、B、C、D 是不同类型的项目 - 项目自己排序(这样当我有 4 个列表时,新项目正在放置本身在正确的列表中,而不是具有管理库存、检查项目类型然后将其放置在正确列表中的功能?

一个都没有。您应该正确设计基类的接口,因此当您使用指向基类的指针时,您不需要知道它的实际类型,您只需使用接口。由于您的问题中没有足够的信息,因此很难向您提供更多详细信息。

注意:直接使用dynamic_cast 或具有模拟它的函数(例如从虚拟函数返回枚举,为您提供特定类型)几乎总是设计不当的标志,尽管有时您可能会由于某些技术原因使用该快捷方式原因。但是设计您的应用程序并从一开始就考虑如何检测实际类型 - OO 设计的绝对错误方法。

注 2:由于使用了继承和虚函数,我假设您正在进行面向对象的设计。尽管 C++ 是一种多范式语言,但您可以用不同的方式解决您的问题。例如,您可以枚举类型为ABCDstd::variant,并使用visitor 单独处理每种类型或使用模板函数通用处理。但这是与 OOD 不同的方法,在这种情况下,您的类可能根本不需要公共基础。当然,您可以将它们混合在一起,但通常这不会带来好的设计。当你混合不同的范式时,你会从每个范式中得到最糟糕的结果。

【讨论】:

  • 我向您保证,在处理数据而不是功能时,这在现实世界中根本不可能。如果这里有空的话,我会写一千个例子。我在对 OP 原始问题的评论中给出了非常简短的描述。
  • 在我现在正在关注的一个项目中,我有一个来自 BaseResponse 解析器的 BaseResponse、一个来自 FooParser 的 FooResponse 和一个来自 BarParser 的 BarResponse。每个响应都有其具体类型的特定数据成员,但如果是 BaseResponse,则它们都共享数据成员。在解析之后,有一种方法可以将不同的响应映射到另一个系统中的某个对象。您不能根据基础接口来编写它。您必须映射具体响应类型的特定数据成员。
  • @ChristopherPisz 我在回答中已经提到,有时保持“理想”OOD 是不切实际的,你必须走捷径。但是 OP 问题显示了错误的方法 - 他想处理该函数中的每种具体类型,这是非常不同的。
  • @ChristopherPisz “你不能用基地的接口来写。”你当然可以,那会有多实用 - 不同的问题。例如,有可能做出这样的决定:“在解析之后,有一种方法可以将不同的响应映射到另一个系统中的某个对象。”不合适。抽象设计很难给出更多细节。
  • 好的,伙计。我有 20 年和 100 个项目,由 5000 人写了不同的说法,但我不会坐在这里整天在 500 个字符的文本框中争论它。接口没有数据成员,也没有地址。接口提供与 METHODS 的合约。提供一个知道具体类型数据成员的方法是完全错误的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-15
  • 2018-08-26
  • 2011-04-21
  • 1970-01-01
相关资源
最近更新 更多