C++ Learning Road (9): Object Model Introduced from Diamond Inheritance

One, single inheritance

class A {int a;};
class B : public A {int b;};

Ordinary single inheritance relationship, the size of the class is determined by the size of its virtual table pointer and non-static member function. Therefore, the size of the above sizeof(A) is 4.

Class B publicly inherits A, and the object model is as follows:

  non-static member of class A (4 bytes)

  non-static member of class B (4 bytes)

Therefore, the size of class B is 8 bytes.

 

2. Multiple inheritance

class A {int a;};
class B {int b;};
class C : public A, public B {int c;};

Ordinary multiple inheritance relationship, here is similar to the above single inheritance. The object model given directly to class C is as follows:

  non-static member of class A (4 bytes)

  non-static member of class B (4 bytes)

  non-static member of class C (4 bytes)

Therefore, the size of class C is 12 bytes.

 

3. Ordinary inheritance with virtual functions

(1) Class object model with virtual functions

C++ introduced virtual functions, that is, the concept of polymorphism. If there is a virtual function in a class, when the object of this class is instantiated, the 4 bytes starting from its first address store the virtual function table pointer (vptr), and vptr points to a virtual table (understood as an array of structures) , each location in the array stores the actual address of the virtual function. (ps: The size of a class is related to its non-member variables, so if a class contains only virtual functions, its size is only one virtual table pointer, which is 4 bytes)

class A
{
    virtual void test(void);
    int a;
};

Therefore, the size of the above class A is, one vptr plus one member variable, which is 8 bytes.

 

(2) Ordinary single inheritance with virtual functions

class A
{
    virtual void test(void);
    int a;
};

class B : public A
{
    int b;
};

Class B directly inherits class A. Since there is a virtual function in class A, there will also be a vptr virtual table pointer in the object of class B, and point to a virtual table for rewriting the test function. The object model of class B is as follows:

  vptr of class B (4 bytes) -----> points to a virtual table

  non-static member of class B (4 bytes)

  non-static member of class A (4 bytes)

Therefore, the size of class B is 12 bytes.

 

4. Virtual inheritance of class objects with virtual functions

class A
{
    virtual void test(void);
    int a;
};

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

The object model given directly to class B is as follows:

  vptr of class B (4 bytes) -----> points to the virtual table, the newly added virtual function is placed in its own virtual table

  non-static member of class B (4 bytes)

  The vptr of class A (4 bytes) ------> points to the virtual table, and the rewritten virtual function is placed in this virtual table. saveB::test()

  non-static member of class A (4 bytes)

Therefore, the size of class B is 16 bytes.

 

5. Diamond Inheritance

The so-called diamond inheritance is a special kind of multiple inheritance relationship, which combines multiple inheritance and virtual inheritance. As shown in the figure:

 

The combined code is as follows:

class X {};
class Y : public virtual X {};
class Z : public virtual X {};
class A : public Y, public Z {};

If the size of the above four classes is output through sizeof, the result is: 1, 4, 4, 8.

 

 (1), the size of the empty class

If C++ defines a class as an empty class, a char (1 byte) will be inserted by the compiler by default, so that the two objects of the class can have unique addresses in memory. So the above sizeof(X) result is 1

 

(2), the size of the virtual inheritance class

In the subclass of virtual inheritance, the subclass will add a form of pointer in addition to vptr. This pointer either points to the virtual base class sub-object, or points to a related table. The table stores either the address of the virtual base class sub-object or its offset. This pointer is called bptr. (When vptr and bptr exist at the same time, some compilers will optimize them and combine them into one pointer)

Therefore, the above Y and Z contain the pointer bptr (occupying four bytes), and inherit the non-static member variables of X (occupying 0 bytes), so the results of sizeof(Y) and sizeof(Z) are both 4.

 

(3), the size of class A

A is directly multi-inherited from Y and Z. Since X is a virtual base class (all subclasses are virtual inheritance), there will only be a copy of X class in A. The object structure of the entire A is:

  bptr of class Y (4 bytes)    

  non-static member of class Y (0 bytes)  

  bptr of class Z (4 bytes)

  non-static member of class Z (0 bytes)

  non-static member of class A (0 bytes)

  non-static member of class X (0 bytes)

So sizeof(X) results in 8. Here are the order of Y and Z from top to bottom, which is determined by the inheritance order of class A.

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325287028&siteId=291194637