1

我从未见过用作虚拟和非虚拟基础的类(即,如果某个类打算成为祖先,那么我们通常会提前知道继承的类型——虚拟或非虚拟)。

所以我认为在 C++ 中有一个容易出错的自由来专门化基类列表中的“虚拟”继承。最好将基类本身指定为“虚拟”

或者也许我错了?

如果不是,任何人都可以描述一些技术来防止这种“虚拟”类的意外非虚拟继承吗?

或者在即将到来的 c++ 标准中有一些观点?

(对不起,如果重复)


一些例子

1) ReferenceCounted 类作为一些基于引用计数的智能指针可以指向的所有类的基础。我们需要防止此基本实例(和引用计数器)的重复。除了优化之外,没有理由将此类用作非虚拟基础。

2)接口的层次结构和相应的实现层次结构(在这种情况下,接口层次结构必须是“虚拟的”)

// 接口:

结构基面{
  无效虚拟函数()= 0;
};

结构 DerivedIface:公共虚拟 BaseIface{
  无效 some_another_func()=0;
}


// 实现

类 BaseImpl:公共虚拟 BaseIface{
  无效虚拟 func(){....};
}

类 DerivedImpl:公共 BaseImpl,公共虚拟 DerivedIface{
  无效 some_another_func(){...};
}

我怀疑在许多情况下,非虚拟继承不是概念上的需要,它仅用于减少虚拟继承开销(有时用于将 static_cast<> 用于驱动的​​能力:)

请注意,Java 仅对接口使用虚拟(就 c++ 而言)继承,而且我不知道有任何抱怨这种语言缺乏“非虚拟”(它本质上是比 c++ 表达力差的语言,但这个“特性”不是它的主要过错 :)。

4

1 回答 1

1

在基类中没有太多方法可以做到这一点(你也不想这样做)。将基类用于虚拟和非虚拟继承是完全合理的。

您真正想要的是在最派生类中指定虚拟继承,目前必须在中间类中指定。不幸的是,我没有看到太多的解决方法——即使当一个类从两个(或更多)其他类派生出来时(主要)变得有必要,每个类都有一个共同的基础,虚拟继承确实控制了这两个类类是编译的,所以如果你(只)在最派生的类中指定它,你最终会得到类似的东西export,你可能需要返回并基于指定 virtual 的最派生类重新编译那些中间类继承(并且有一些方法来存储以两种方式编译的中间类,因为它可能以一种或两种方式使用)。

于 2010-08-10T15:03:59.750 回答