问题
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.
回答1:
Virtual inheritance is only relevant if classes are to inherit from
Foo
. If I define the following:
class B {};
class L : virtual public B {};
class R : virtual public B {};
class D : public L, public R {};
Then the final object will only contain one copy of B
, shared by both
L
and R
. Without the virtual
, an object of type D
would contain
two copies of B
, one in L
, and one in R
.
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.
回答2:
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 of virtual
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,
class Bar;
class Foo : public virtual Bar
class Other : public Foo // <--- one more level child class
So, now Bar::Bar()
will be called directly from Other::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:
class Final {
Final() {}
friend class LastClass;
};
class LastClass : virtual Final { // <--- 'LastClass' is not derivable
...
};
class Child : public LastClass { // <--- not possible to have object of 'Child'
};
回答3:
In this case, no difference. Virtual inheritance is related to sharing superclass subobjects instances by derived classes
struct A
{
int a;
};
struct B : public virtual A
{
int b;
}
struct C : public virtual A
{
int c;
};
struct D : public B, public C
{
};
There's a single copy of the member variable a
in the instance of D
; If A
was not a virtual base class, there would be two A
subobjects in instance of D
.
回答4:
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.
来源:https://stackoverflow.com/questions/8148470/virtual-inheritance-confusion