这是多重继承的良好用法吗?

Is this a good use of multiple inheritance?

本文关键字:用法 多重继承      更新时间:2023-10-16

我发现了一些代码,其中基类的派生被用作一种标志,将某些对象标记为属于特定组:

// Base type for any item to be stored in a Storage.
class Item {     // trivial class (as shown here)
public:
   virtual ~Item() {}
};
class BaseItem;   // complex class
class ItemA : public BaseItem, public Item;   // complex class
class Storage;

由于已经有一个基类可以从中派生,因此我们得到了多重继承。

考虑到多重继承的性能成本以及此代码必须高效的事实,这是否是一种好方法?

一个简单的标志会是更好的选择吗?

主要问题是:">ItemA的行为与BaseItemItem的行为有何不同?事实上,你甚至可以问:"BaseItem的行为与Item有什么不同?继承主要用于您希望继承类型之间的常见行为,但这些类型之间的行为存在一些差异(参见"为什么要使用继承?如果这些项目在行为上完全没有区别,那么有更简洁的方式来表示每个项目的一些特殊"类型",而不必定义实际的......为他们键入,例如,使用您已经提议的标志。如有疑问,请保持简单。

在性能方面...好吧,在这个阶段甚至根本不考虑性能:是的,使用虚拟成员对运行时的影响非常小,但对于几乎所有目的来说,这都是无关紧要的。然而,通过多重继承,很容易迅速制造出没有人愿意试图理解的脑痛混乱。尽管如此,使用MI还是有一些很好的理由,但要非常非常小心。

当然,

这完全没问题。这就是C++的做法。例如,basic_istreambasic_ostream 都继承自基类basic_ios 。然后basic_iostream继承了basic_istreambasic_ostream。看起来像这样:

https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-3.4/classstd_1_1basic__iostream__inherit__graph.png

一个简单的标志可能是更好的选择,但它取决于。我已经看到这种类型的琐碎基类用于允许编译时检查对象是否被允许做某事。

执行此操作或使用标志的运行速度是否更快取决于您如何使用它。在我给出的示例中,代码随后使用 dynamic_cast s 从基指针获取派生指针。这会产生运行时成本,这可能使标志更有效率,但程序员希望编译时检查以防止其他程序员尝试错误地使用系统,因此他做出了权衡。

虚拟表确实有性能开销,但开销不大(我执行的测试使我相信性能仅比 switch 语句慢一点(,所以我不会担心这一点,除非您正在编写嵌入式系统或编写每秒将执行数百万次或更多的函数。