Class {
Public:
A () {PTR = "abcdefg ";};
~ A (){};
Virtualvoid print (){
Printf ("% s \ r \ n", PTR );
}
Virtualvoid printa (){
Printf ("A: % s \ r \ n", PTR );
}
Public:
Char * PTR;
};
Class B: virtual public {
Public:
B () {PTR = "bbbbbbbbbbbbbbbbb"; bv = 0 xbbbbbbbbbb ;}
~ B (){};
Virtualvoid print (){
Printf ("B: Print [% s] \ r \ n", PTR );
}
Virtualvoid printb (){
Printf ("B: print1 [% s] \ r \ n", PTR );
}
Public:
Intbv;
};
Class C: virtual public {
Public:
C () {PTR = "ccccccccccccccccc"; cv = 0 xcccccccccc ;}
~ C (){};
Virtualvoid print (){
Printf ("C: [% s] [% s] \ r \ n", PTR, PTR );
}
Virtualvoid printc (){
Printf ("C: [% s] [% s] \ r \ n", PTR, PTR );
}
PRIVATE:
Intcv;
};
Class D: Public B, public c {
Public:
D () {v = 0 xdddddddd ;}
~ D (){};
Virtualvoid print (){
Printf ("D: [% s] [% s] \ r \ n", A: PTR, B: PTR );
}
PRIVATE:
Intv;
};
In the above example, the memory layout of D is inherited by virtual machines.
B: vfptr |
The virtual function table created by D relative to B, excluding the virtual function. |
B: btoaofsetptr |
Address of the Offset Value from object B to object A (B: btoaofsetptr + 4) |
B: memberverb |
B Member variable |
C: vfptr |
D is a virtual function table created in comparison to C, which does not include a virtual function |
C: ctoaofsetptr |
Address of the Offset Value from object B to object A (C: ctoaofsetptr + 4) |
C: memberverb |
C member variable |
D: memberverb |
D member variable |
00000000 |
Separate |
A: vfptr |
D. The virtual function table created with respect to |
A: memberverb |
A member variable |
Note: functions covered by a in B and C must be overwritten in D. Otherwise, the compilation prompts that the Declaration is uncertain. The offset address from the sub-object to the object A must be 4, the content is correct.
Class {
Public:
A () {PTR = "abcdefg ";};
~ A (){};
Virtualvoid print (){
Printf ("% s \ r \ n", PTR );
}
Virtualvoid printa (){
Printf ("A: % s \ r \ n", PTR );
}
Public:
Char * PTR;
};
Class B {
Public:
B () {PTR = "bbbbbbbbbbbbbbb ";}
~ B (){};
Virtualvoid print (){
Printf ("B: Print [% s] \ r \ n", PTR );
}
Virtualvoid printb (){
Printf ("B: print1 [% s] \ r \ n", PTR );
}
Public:
Char * PTR;
};
Class C: Public A, public B {
Public:
C () {CV = 0 xcccccccc ;}
~ C (){};
Virtualvoid print (){
Printf ("C: [% s] [% s] \ r \ n", A: PTR, B: PTR );
}
Virtualvoid printc (){
Printf ("C: [% s] [% s] \ r \ n", A: PTR, B: PTR );
}
PRIVATE:
Intcv;
};
Class D: Public B, public c {
Public:
D () {v = 0 xdddddddd ;}
~ D (){};
Virtualvoid print (){
Printf ("D: [% s] [% s] \ r \ n", A: PTR, B: PTR );
}
PRIVATE:
Intv;
};
In the above example, the memory layout of D is inherited by virtual machines:
A: vfptr |
D: The virtual function table created by C compared with |
A: memberverb |
A member variable |
B: vfptr |
The virtual function table created by D relative to B and C |
B: memberverb |
B Member variable |
C: memberverb |
C member variable |
D: memberverb |
D member variable |
Note: When multiple parent classes have members of the same name, the scope of the name must be specified.
About the structure:
The destructor of A Class must reset its own virtual function table pointer so that it is inherited by other classes as a parent class, when the subclass destructor calls it again, it can shield the subclass from overwriting itself, because the resources of the subclass have been released, if you do not reset the virtual function table, the Destructor will call the subclass function instead of its own function if it is overwritten by the quilt class.