Mixing virtual and non-virtual inheritance of a base class

后端 未结 3 1721
醉话见心
醉话见心 2020-12-09 08:51

This is the code:

struct Biology
{    
    Biology() { cout << \"Biology CTOR\" << endl; }
};

struct Human : Biology
{    
    Human() { cout &l         


        
相关标签:
3条回答
  • 2020-12-09 09:08

    Non virtual inheritance is an exclusive relationship, like membership. A class can be the non-virtual base class of one other class in a given complete object.

    This implies that a class can override virtual functions of a non virtual base class without causing conflicts or issues.

    A constructor can also initialize non virtual bases reliably.

    Only virtual bases can be direct base classes of many indirect bases of a complete object. Because a virtual base class can be shared, overriders can conflict.

    A constructor can try to initialize a virtual base subobject in the ctor-init-list, but if the class is further derived, that part of the ctor-init-list will be ignored.

    0 讨论(0)
  • 2020-12-09 09:13
    1. All the base classes that inherit virtually from Biology share one instance of Biology base between them.
    2. All the base classes that inherit non-virtually from Biology have one instance each of Biology.

    You have one base in each category, therefore you have one instance of Biology brought in by Human (and in principle shared with others) and one instance brought in by Animal (never shared with any other base class).

    0 讨论(0)
  • 2020-12-09 09:19

    It's clear from the output that two Biology objects are instantiated. That is because you've made only one inheritance virtual. Two base class instances is the cause of ambiguity in dreaded diamond problem and the solution is to make (as we know) both inheritances of Biology virtual.

    Recap of the hierarchy:

    Biology  Biology
       |       |     # one and only one inheritance virtual
     Human   Animal
        \     /
        Centaur
    

    Ok, let's read the output again with these rules in mind:

    • Base classes are constructed before derived classes.
    • Base classes are constructed in order in which they appear in the base-specifier-list.
    • Virtual base classes are constructed before non-virtual ones by the most derived class - see this.

    1st output - Animal virtually inherits from Biology:

    Biology CTOR     # virtual base class inherited from Animal
    Biology CTOR     # non-virtual base class of Human
    Human CTOR       # Human itself
    Animal CTOR      # Animal's virtual base class already constructed
    Centaur CTOR
    

    2nd output - Human virtually inherits from Biology:

    Biology CTOR     # virtual base class inherited from Human
    Human CTOR       # Human's virtual base class already constructed
    Biology CTOR     # non-virtual base class of Animal
    Animal CTOR      # Animal itself
    Centaur CTOR
    

    More informative standard paragraph ([class.base.init]/10):

    In a non-delegating constructor, initialization proceeds in the following order:

    — First, and only for the constructor of the most derived class (1.8), virtual base classes are initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes, where “left-to-right” is the order of appearance of the base classes in the derived class base-specifier-list.

    — Then, direct base classes are initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).

    ...

    0 讨论(0)
提交回复
热议问题