【问题标题】:In C++, should I almost always use virtual inheritance?在 C++ 中,我应该几乎总是使用虚拟继承吗?
【发布时间】:2011-05-31 10:07:27
【问题描述】:

我从this entry 看到虚拟继承将 sizeof(pointer) 添加到对象的内存占用。除此之外,默认情况下仅使用虚拟继承和仅在需要时使用传统继承对我有什么缺点吗?似乎它会导致更多面向未来的类设计,但也许我错过了一些陷阱。

【问题讨论】:

  • 基类的初始化顺序对于大多数人来说变得不明显。因此维护成本增加。
  • 虚拟继承仅在某些实现上添加内部指针。 Itanium ABI 不使用内部指针,只使用 vptr。

标签: c++ multiple-inheritance virtual-inheritance


【解决方案1】:

缺点是

  1. 所有类都必须始终初始化其所有虚拟基(例如,如果 A 是 B 的虚拟基,并且 C 派生自 B,它还必须初始化 A 本身)。
  2. 您必须在使用static_cast 的任何地方使用更昂贵的dynamic_cast(可能是问题,也可能不是问题,具体取决于您的系统以及您的设计是否需要它)。

仅第 1 点就不值得,因为您无法隐藏虚拟基地。几乎总有更好的方法。

【讨论】:

  • @SuperElectric:为什么(1)很可怕?如果没有初始化基础子对象会更好吗? ;)
  • 诸如“不值得”之类的评论表明完全无法理解虚拟基的用途:在子类化抽象时必须始终使用虚拟继承。没有变通方法或其他可能性,如果您未能使用它,您将无法使用抽象的多个子类化而不返回并修复您的设计错误,从而破坏封装。
  • @Yttrill @SuperElectric “这不值得”我的意思是让自己陷入需要多重虚拟继承的境地。至此,您的设计太复杂了。至于第(2)点,它不会用static_cast编译。
  • @AlexB 我不明白 (1)。所有类都不会一直初始化它的所有基础(非虚拟基础)?
  • @AlexB 好的,这意味着 C 构造函数必须显式初始化 A(不仅仅是 B)。
【解决方案2】:

根据我的经验,几乎不需要虚拟继承(相对于虚拟方法)。在 C++ 中,它用于解决 "diamond inheritance problem",如果您避免多重继承,这实际上不会发生。

我很确定我从未在 C++ 书籍之外遇到过虚拟继承,其中包括我编写的代码和我维护的数百万行系统。

【讨论】:

  • 标准 C++ I/O 流库使用虚拟继承。但是,是的,除此之外,它通常非常罕见。
  • Greg:+1 对整个虚拟继承混乱的出色概括。
  • 嗯...我已经知道它的用途(我正在考虑使用它),并且我知道它很少见(我用 c++ 编写代码),但提出的问题是“什么是虚拟继承的缺点”。
  • 另一个可能的答案是虚拟继承使您的代码更难阅读。对于那些不经常遇到虚拟继承的人,他们将不得不了解它并施加额外的认知负担,即在阅读您的代码时记住它的含义。对于那些确实理解它的人,他们会想知道如果你的类都没有真正使用菱形继承,为什么你要使用一个不必要的特性。 YAGNI 原则适用于这种情况。
猜你喜欢
  • 1970-01-01
  • 2012-07-03
  • 2016-03-26
  • 2011-01-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多