【问题标题】:dynamic_cast vs exposing virtual functions in parent class (C++)dynamic_cast 与在父类中公开虚函数(C++)
【发布时间】:2012-09-14 15:26:50
【问题描述】:

我有一个父类“base”和另一个继承自“base”的“派生”类。

“派生”有1个方法cH1。

如果我这样做:

base* b = new derived();

我希望能够做到这一点:

b->cH1();

显然我不能,有两种解决方案:

  • 要么将 cH1 声明为 base 中的纯虚拟。
  • 或者这样做:

    dynamic_cast<derived*>(b)->cH1();
    

哪个是更好的做法?

【问题讨论】:

  • 请关闭大写锁定键; PARENT 暗示名字是宏; parent 是常用的用法。
  • 我想说,你脑子里最大的问题可能是“父母”和“孩子”这两个词的使用。对于基类和派生类,这些是非常糟糕的隐喻:通常来说,子类通常不是父类,也不是更具体的父类实例。一个更好的比喻是“基类”和“派生类”。
  • @PeteBecker 和@KerrekSB:很好的建议。此外,我建议将cH1(对于通用方法名称有点晦涩和奇怪)更改为m1method1

标签: c++ dynamic-cast


【解决方案1】:

如果cH1 方法在语义上适用于base,则使其成为base 的方法。 否则,将cH1 留给derived,并使用dynamic_cast。 我认为你的类的语义应该推动你的选择。

例如,如果您有一个基类Vehicle 和派生类CarMotorbikeAircraft,则类似TakeOff() 的方法的语义与Aircraft 兼容,但与@987654333 不兼容@ 或 Motorbike,因此您可能希望将 TakeOff() 设为 Aircraft 方法,而不是 Vehicle 方法。

【讨论】:

  • 我一直听到这个词,但我一直不明白:/ 你所说的“语义上”适用于 base 是什么意思?
  • @Kam:例如,如果您有一个基类Vehicle 和派生类CarMotorbikeAircraft,则类似TakeOff() 的方法具有与Aircraft 但不能与 CarMotorbike 一起使用,因此您可能希望将 TakeOff() 设为 Aircraft 方法,而不是 Vehicle 方法。
【解决方案2】:

dynamic_cast 更简洁、更灵活,但速度有点慢。

请记住,当您使用 dynamic_cast 检查返回的指针是否为 NULL 时。

【讨论】:

  • dynamic_cast 如何更简洁、更灵活?在某些情况下dynamic_cast 可能是合理的,但从给出的信息来看,我认为我们不能断定这是其中之一。 (总的来说,使用虚函数更干净。)
  • @JamesKanze,如果父类没有被与该类无关的函数弄乱,它会更干净。我同意我们需要更多关于课程细节的信息才能真正了解。
【解决方案3】:

首先,为了使用dynamic_castbase必须至少有一个虚函数。

其次,使用dynamic_cast通常是设计错误的标志。如果derived 确实是base 的子对象,那么derived 对象应该能够出现在期望base 对象的任何位置,这通常意味着base 具有虚函数,可以是纯虚函数,也可以是纯虚函数。不是,derived 会覆盖其中的部分或全部。

虽然不知道 cH1 做了什么,但不可能推荐一种方法。

【讨论】:

  • 这并不总是一个错误 - 有时您需要一个对象集合,这些对象有一些共同点,但没有其他共同点。
  • 在具体类中使用dynamic_cast 几乎总是一个错误,但一个类(或一组类)支持扩展接口的情况并不少见。在这种情况下,dynamic_cast 是支持访问扩展接口的一种方式。
  • 我已经强调了通常这个词,因为它似乎被忽略了。我没有说这总是一个错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多