Virtual Inheritance Confusion

安稳与你 提交于 2019-12-23 09:59:42

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!