我从未在专业软件中使用它,即使在我们的商店和我工作的其他人,我们设计大型系统。我与虚拟继承混淆的唯一一次是在我公司的采访中。尽管如此,我还是在下班后玩弄了它。
你们使用它吗?您是否了解它的工作原理(最流行的编译器供应商如何实现它)?我真的想知道如何在专业软件中使用它,如果有的话。诀窍和技巧也将受到赞赏。
对我来说,虚拟继承只是一个臭名昭着的钻石问题的解决方案。因此,它从未在我们的软件中找到它的方式,因为我们在我们的架构MI中没有得到钻石。
感谢。
答案 0 :(得分:6)
虚拟继承的要点是防止派生类继承不同上级类的多个副本。在任何可能存在多重继承的情况下都会发生这种情况 - 正如您正确指出的那样,“钻石问题”,也就是说继承图是DAG而不是严格树的位置。
C++ FAQ goes into it in some detail。我还推荐C ++ FAQ Book;我曾经为作者工作,他们非常好。
答案 1 :(得分:5)
即使在我们的商店,我也从未在专业软件中使用它,
您使用iostream
吗?我们的确是。查看iostream的设计,你就会知道你一直在使用虚拟继承。
答案 2 :(得分:4)
虚拟继承也可用于使类成为最终类,即使其成为其他类无法从中派生的类。我从Stroustroup中抓取了一次这个技巧( http://www.research.att.com/~bs/bs_faq2.html#no-derivation ,请参阅下面的更新超链接和来源):
此问题的另一个变体,如何根据逻辑原因防止派生,在C ++ 11中有一个解决方案。例如:
[...]
对于较旧的编译器,您可以使用一种有点笨拙的技术: 类可用;
class Usable_lock { friend class Usable; private: Usable_lock() {} Usable_lock(const Usable_lock&) {} }; class Usable : public virtual Usable_lock { // ... public: Usable(); Usable(char*); // ... }; Usable a; class DD : public Usable { }; DD dd; // error: DD::DD() cannot access // Usable_lock::Usable_lock(): private member
C ++已收到final
个关键字in the meanwhile:
为什么C ++没有最终关键字?
导致:
我可以阻止那些来自我班级的人吗?
是的,但你为什么要这样做?有两个常见的答案:
- 提高效率:避免我的函数调用是虚拟的
- 为了安全:确保我的类不被用作基类(例如, 确保我可以复制对象而不必担心切片)
根据我的经验,效率原因通常是错位的恐惧。在C ++中,与使用普通函数调用的替代解决方案相比,虚函数调用非常快,以至于它们对使用虚函数设计的类的实际使用不会产生可测量的运行时开销。请注意,虚函数调用机制通常仅在通过指针或引用进行调用时使用。当直接为命名对象调用函数时,虚拟函数类开销很容易被优化掉。
如果确实需要“限制”类层次结构以避免虚函数调用,那么可能会首先询问为什么这些函数是虚拟的。我已经看到了一些示例,其中性能关键函数是虚拟的,没有任何理由,只是因为“这就是我们通常这样做的方式”。
此问题的另一个变体,如何根据逻辑原因防止派生,在C ++ 11中有一个解决方案。例如:
struct Base { virtual void f(); }; struct Derived final : Base { // now Derived is final; you cannot derive from it void f() override; }; struct DD: Derived {// error: Derived is final // ... };
......然后导致这个答案的初步通过。
答案 3 :(得分:2)
如果您的架构不使用多重继承,我不明白为什么您要使用它。
如果您碰巧使用MI,我无法理解为什么不会使用虚拟继承。除了记住在正确的位置添加virutal关键字之外,似乎没有任何缺点。
答案 4 :(得分:0)
我曾与几家需要使用它的商业图书馆合作过。例如,路透社提供的用于访问实时金融市场数据的库曾经要求您从几个基类派生您的监听类(不知道它是否仍然存在),这需要虚拟继承。一旦你意识到你必须使用它,这没什么大不了的 - 这个事实并没有完全记录下来。
答案 5 :(得分:0)
要获得有关虚拟继承的更多见解,您还可以查看此帖子:http://cpptalk.wordpress.com/2009/08/11/constructor-selection-with-virtual-inheritance/ 我对这个机制有深入的了解,所以如果你有一个具体的问题 - 请继续问问。