【问题标题】:Does using a static_cast on a polymorphic object indicate a design flaw?在多态对象上使用 static_cast 是否表明存在设计缺陷?
【发布时间】:2013-04-19 19:50:24
【问题描述】:

我知道应该避免 dynamic_cast,但假设我的程序中有一个 Base 类的对象 x,我知道在执行的某个时刻它也是 Derived 类(继承自 Base)。使用 static_cast 向下转换以调用派生方法等是否可以接受?或者这是否表明存在设计缺陷?

【问题讨论】:

  • 你能举个例子吗?您通常向下转换指针或引用。您没有两种类型的对象。
  • “应避免dynamic_cast”是一个愚蠢的建议(就像这样的每一个绝对陈述),有合法的用例。
  • 有时你必须这样做,但是是的,它通常表明,如果不是设计缺陷,至少是次优设计
  • @MatteoItalia 当然,这种建议应始终以“一般”为前缀。建议实际上应该是“通常使用dynamic_cast 表示您的程序中存在设计缺陷,并且应该有很好的理由这样做。”然而,我认为,我们应该教导人们不要将这种建议视为绝对的。
  • "是否可以使用 static_cast 向下转换以调用派生方法等?" 是的,绝对可以,只要您肯定 它实际上是一个Derived

标签: c++


【解决方案1】:

它表示与使用dynamic_cast 完全相同的设计缺陷。事实是,如果您使用指向基类的指针,则应该意味着您只使用传递的对象,就好像它们是该基类一样。如果您必须确定对象的动态派生类型,那么您可能不应该使用指向 base 的指针。

为此使用static_cast 比使用dynamic_cast 更危险一点。如果您要转换的类型确实是正确的,那么您只有明确定义的行为。使用dynamic_cast,至少它会告诉您是否不是。

与任何建议一样,总会有例外。问问自己,基指针类型在这里是否真的合适。我们使用多态性来表示“我们只想要Fruit!我不在乎它是Apple 还是Banana - 我们会一视同仁!”如果您没有将所有对象都视为基本类型,那么您可能需要重新考虑。正如 Mark Ransom 在他的回答中给出的一个例子,有时你真的想以这种方式沮丧。

【讨论】:

  • 谢谢。这很有意义。我正在 MPI 中编写一个并行代码,其中一些处理器比其他处理器存储有关某些对象的更多信息(因此,派生类)。但是在并行代码中,每个人都必须执行相同的代码,所以我传入 Base 类并使用 if 语句来确定我的代码的行为。我可以看出这是多么可疑,我会重新考虑这一点。
  • 另一个例外是使用static_castfinal 进行优化。您有一个抽象接口,有时您将在其中连续调用许多虚拟函数。通过向下转换为选择的具体类型,然后调用 final virtual 方法,您可以消除 virtual 方法调用开销,甚至可以完全省略调用,同时保持它完全通用,并对库用户隐藏这些优化.我相信Google Protocol Buffers 使用了这种技术。
【解决方案2】:

它有合法用途。没有它Curiously Recurring Template Pattern (CRTP) 是不可能的。

【讨论】:

  • 一个很好的例子,说明你确实知道对象的派生类型(除非它滥用 CRTP)。
  • static_assert( std::is_base_of< Derived, CRTP_Template_Name<Derived> >, "CRTP used incorrectly" ); 非常确定。
【解决方案3】:

imo 是的,它可能表明存在设计缺陷。如果你知道它是某种类型的派生类,为什么它作为基类传递?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-07
    • 1970-01-01
    • 2011-08-29
    • 2017-01-20
    • 1970-01-01
    • 2021-06-30
    • 2019-11-10
    • 2012-03-06
    相关资源
    最近更新 更多