4

Sample code in C++:

class A {
  public:
    A(int) {}
};

class B : public virtual A {
  public:
    B(int b) : A(b) {}
};

class C : virtual public A {
  public:
    C(int c) : A(c) {}
};

class D : public B, public C {
  public:
    D() : B(1), C(2){};
};

This is typical code(solution) for diamond problem. I am aware why virtual keyword is used. But the internal mechanism by which the compiler takes care of the issue is not known to me. Now I have come across two different theories about the said mechanism which are as stated below.

  1. When a class is inherited with virtual keyword, compiler adds a virtual base pointer in the derived class. I have checked the size of the derived class and yes it includes the size of an additional pointer. But I don't know where it points to and how does it work when a member of class A is referred in class D in the above example.

  2. For each of the constructors compiler creates two versions of each definition provided by the programmer. Got to know from this link e.g. in the above code. Compiler will generate 2 versions of the constructor of C

     C(int){}           // Version1
    
     C(int):A(int){}    // Version2 
    

    And two different versions of constructor B

     B(int){}           // Version1
    
     B(int):A(int){}    // Version2
    

    So when D is constructed then compiler will generate either of the below codes

    D() : B(), C(2) {}  // Version1
    
    D() : B(1), C() {}  // Version2
    

    So as to make sure that only one instance of A is created and hence duplicate copy of A is avoided.

Please help me to understand the internal mechanism.

curiousguy
  • 8,038
  • 2
  • 40
  • 58
paper.plane
  • 1,201
  • 10
  • 17
  • 1
    @Ron Please read the actual post before flagging it – George Aug 10 '17 at 11:51
  • @paper.plane the question may be a bit theoretical for SO... also, the actual implementation of virtual inheritance is compiler dependent... to see what the standard actually says look at: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf at page 231 – George Aug 10 '17 at 11:53
  • 1
    @ Ron Again, I think you may have not read the question and just googled the title... op doesn't seem to want to know what virtual does (or what a virtual base class does) but rather how and why the internal object model for said class and inheriting classes is generated – George Aug 10 '17 at 11:55
  • 4
    The "internal mechanism" is compiler-dependent, so in order for this question to be answerable by Stack Overflow standards, you need to narrow this down a bit by specifying a particular toolchain. – Cody Gray - on strike Aug 10 '17 at 11:57
  • @George I read it and I am well aware of academia's affinity towards the multiple inheritance and the so called diamond problem. I will retract the flag however. – Ron Aug 10 '17 at 11:57
  • 1
    One option is for the compiler to pass a secret parameter to `B(int)` and `C(int)` telling them if they should call `A(int)` or not. The language standard just tells us the effect, not how it is accomplished. – Bo Persson Aug 10 '17 at 12:12
  • "_compiler adds a virtual base pointer in the derived class_" not every compiler implements virtual bases the same way (but nearly every existing compiler implements non virtual bases and virtual functions the same way) – curiousguy Aug 18 '17 at 03:00

1 Answers1

1

A common usage (not specified by any standard!) is to first create an instance of the virtually inherited object and put a pointer to that in the vtables. So here is what happens:

  • creation of a A: nothing special
  • creation of a B: a A is constructed and a link to it is added in B vtable
  • creation of a D: a A is constructed first, then B and C and each contain a link to A in their vtable. That allows when you get a pointer to a D object, to cast it to a pointer to B and C and each of the pointers will still know where are its A members.

But this is no more than a theorical answer of what could be an implementation. I do not say that an actual implementation (say gcc, clang or microsoft vc) follow exactly that. But you can use it for example if you have to mimic virtual inheritance in plain C language.

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • Does it create a v-table for virtual inheritance? As mentioned in my question , I agree to the point that it would add a virtual-base pointer. But isn't it different from virtual-pointer? Because in the above example the size of class B is say N (size of a pointer). But if a virtual function is added in class B then the size will become 2N.(I have checked this) Because compiler will add v-pointer and v-table additionally. My question is for virtual inheritance alone, will compiler add v-table? – paper.plane Aug 10 '17 at 13:01
  • @paper.plane: it may. As I said, this is just a possible implementation. If you want to know for a specific implementation, you should said exactly what compiler (and version and build options) you target. – Serge Ballesta Aug 10 '17 at 13:04
  • 1
    A vtable is static. It is never changed, and cannot contain pointers to dynamic objects! – curiousguy Aug 15 '17 at 04:06