虚拟继承混乱
我正在阅读有关继承的内容,并且有一个我几个小时都无法解决的主要问题:
给定一个类 Bar
是一个具有 virtual
函数的类,
class Bar
{
virtual void Cook();
};
什么 之间有什么不同
class Foo : public Bar
{
virtual void Cook();
};
:和
class Foo : public virtual Bar
{
virtual void Cook();
};
?经过几个小时的谷歌搜索和阅读,我得到了很多关于它的用途的信息,但没有一个真正告诉我两者之间的区别,这让我更加困惑。
I'm reading about inheritance and I have a major issue that I haven't been able to solve for hours:
Given a class Bar
is a class with virtual
functions,
class Bar
{
virtual void Cook();
};
What is the different between:
class Foo : public Bar
{
virtual void Cook();
};
and
class Foo : public virtual Bar
{
virtual void Cook();
};
? Hours of Googling and reading came up with lots of information about its uses, but none actually tell me what the difference between the two are, and just confuse me more.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
就功能而言,这两个版本之间没有太大区别。对于
虚拟
继承的情况,每个实现通常都会添加一个(类似于vptr
)指针(与虚拟
函数的情况相同)。这有助于避免由于多重继承而生成多个基类副本(钻石继承问题)此外,
虚拟
继承委托调用其基类构造函数的权利。例如,现在
Bar::Bar()
将直接从Other::Other()
调用,并且也将被放置在其他基类中的第一位。此委托功能有助于在 C++03 中实现
final class
(在 Java 中)功能:Functionality wise there is not much difference between the 2 versions. With the case of
virtual
inheritance, every implementation generally adds a (vptr
like) pointer (same as in the case ofvirtual
functions). Which helps to avoid multiple base class copies generated due to multiple inheritance (the diamond inheritance problem)Also,
virtual
inheritance delegates the right to call the constructor of its base class. For example,So, now
Bar::Bar()
will be called directly fromOther::Other()
and also will be placed at the first place among other base classes.This delegation feature helps in implementing a
final class
(in Java) functionality in C++03:仅当类要继承时,虚拟继承才相关
Foo
。如果我定义以下内容:那么最终对象将仅包含
B
的一个副本,由两者共享L
和R
。如果没有virtual
,D
类型的对象将包含两份
B
副本,一份在L
中,一份在R
中。有一些争论认为所有继承都应该是虚拟的(因为
在有影响的情况下,这就是您最想要的
时间)。然而,在实践中,虚拟继承是昂贵的,并且
在大多数情况下,没有必要:在设计良好的系统中,大多数
继承只是从一个或多个继承的具体类的继承
更多“接口”;这样一个具体的类通常不是被设计成
从自身派生出来的,所以没有问题。但有重要的
例外:例如,如果您定义了一个接口,然后
接口的扩展,扩展应该虚拟继承
从基本接口开始,因为具体的实现可能需要
实施几个扩展。或者如果你正在设计 mixin,那么在哪里
某些类只实现了接口的一部分,而最终的
类继承自其中的几个类(每个类的一部分一个)
界面)。最后,是否虚拟继承的标准
或不不是太困难:
如果继承不是公共的,它可能不应该是虚拟的
(我从未见过异常),否则
如果该类没有设计为基类,则不需要
虚拟继承,否则
继承应该是虚拟的。
有一些例外,但上述规则是错误的
安全;即使在以下情况下,虚拟继承通常也是“正确的”
虚拟继承不是必需的。
最后一点:虚拟基必须始终由最常初始化
派生类,不是直接继承的类(并声明
继承是虚拟的)。然而,在实践中,这不是问题。
如果你看看虚拟继承有意义的情况,那就是
总是从接口继承的情况,该接口不包含任何内容
数据,因此(仅)有一个默认构造函数。如果你发现自己
从具有构造函数的类进行虚拟继承,该构造函数采用
争论之后,是时候对设计提出一些严肃的问题了。
Virtual inheritance is only relevant if classes are to inherit from
Foo
. If I define the following:Then the final object will only contain one copy of
B
, shared by bothL
andR
. Without thevirtual
, an object of typeD
would containtwo copies of
B
, one inL
, and one inR
.There is some argument that all inheritance should be virtual (because
in the cases where it makes a difference, that is what you want most of
the time). In practice, however, virtual inheritance is expensive, and
in most cases, not necessary: in a well designed system, most
inheritance will simply be of a concrete class inheriting from one or
more "interfaces"; such a concrete class is usually not designed to be
derived from itself, so there is no problem. But there are important
exceptions: if, for example, you define an interface, and then
extensions to the interface, the extensions should inherit virtually
from the base interface, since a concrete implementation could want to
implement several extensions. Or if you are designing mixins, where
certain classes only implement part of the interface, and the final
class inherits from several of these classes (one per part of the
interface). In the end, the criteron as to whether to inherit virtually
or not isn't too difficult:
if the inheritance isn't public, it probably shouldn't be virtual
(I've never seen an exception), otherwise
if the class is not designed to be a base class, there's no need for
virtual inheritance, otherwise
the inheritance should be virtual.
There are a few exceptions, but the above rules err on the side of
safety; it's usually "correct" to inherit virtually even in cases where
the virtual inheritance isn't necessary.
One final point: a virtual base must always be initialized by the most
derived class, not the class that directly inherits (and declares that
the inheritance is virtual). In practice, however, this is a non-issue.
If you look at the cases where virtual inheritance makes sense, it is
always a case of inheriting from an interface, which will contain no
data, and thus have (only) a default constructor. If you find yourself
inheriting virtually from classes with constructors which take
arguments, it's time to ask some serious questions about the design.
在这种情况下,没有区别。虚拟继承与派生类共享超类子对象实例有关
D
的实例中存在成员变量a
的单个副本;如果A
不是虚拟基类,则D
实例中会有两个A
子对象。In this case, no difference. Virtual inheritance is related to sharing superclass subobjects instances by derived classes
There's a single copy of the member variable
a
in the instance ofD
; IfA
was not a virtual base class, there would be twoA
subobjects in instance ofD
.虚函数是一个在派生类中可能有不同实现的函数(尽管这不是必须的)。
在你的最后一个例子中是虚拟继承。想象一下这样的情况,您有两个从基类(我们称之为“Base”)派生的类(A 和 B)。现在想象一下从 A 和 B 派生的第三个类 C。如果没有虚拟继承,C 将包含“Base”的两个副本。这可能会导致编译时出现歧义。虚拟继承中重要的是,“基”类构造函数(如果有)的参数必须在类 C 中提供,因为来自 A 和 B 的此类调用将被忽略。
Virtual function is a function that will probably have different implementation in derived class (although it's not a must).
In your last example is virtual inheritance. Imagine a case where you have two classes (A and B) derived from a base class (let's call it 'Base'). Now imagine a third class C derived from A and B. Without virtual inheritance, the C would contain two copies of 'Base'. That could lead to ambiguity while compiling. The important thing in virtual inheritance is that the parameters for the 'Base' class constructor (if any) MUST be provided in the class C, because such calls from A and B will be ignored.