I tried it these two days.
Because there is only a VC6 compiler on the hand, only the way VC6 is seen.
My test procedure is as follows #include "stdafx.h" Class MostBase1 {public: MostBase1 (): i (1) {}; int i;}; class mostbase2 {public: mostbase2 (): j (2) {}; int J;};
class base1: public virtual mostbase1, public virtual mostbase2 {}; class base2: public virtual mostbase1, public virtual mostbase2 {}; class derived: public base1, public base2 {}; void f (derived * pderived) {mostbase1 * pbase1 = pderived ; MostBase2 * PBase2 = Pderived; INT K = Pderived-> i; k = pderived-> j; k = pBase1-> i; k = PBase2-> j;} int main (int Argc, char * argv []) { Derived D; F (& D); Printf ("Hello World! / N"); Return 0;} After my testing and viewing assembly code, I know that the virtual base class conversion of VC is as mentioned in INSIDE THE C Objects Model. It is the BASE1 and BASE2 implemented in a Virtual base class table, and there is one __vbct__ptr (size is 4 bytes) to point to a virtual base class table, which stores the Base class in the base class in the base class. Offset, then the data, when Derive is inherited from Base1 and Base2, first is to store Base1 and Base2 __vbct_ptr, then the data, put the data of Base1 and Base2 The same base class is put together with the BASE1 class memory layout ( base2 base1 the same): pvoid * __vbct_base1 ---- virtual base class first address table, in which case the following data __vbct_base1 ---- 00 00 00 00 04 00 00 00 08 00 00 00 ---- mostbase1 in base1 The value of [__vbct_base1 4] is int i; ---- IINT J in the MostBase1 class; ----- MostBase2 class J
The memory layout of the Derived class is as follows: pvoid * __vbct_base1; --- The address of the virtual base class table of the base1 class, where the value changes, the data is as follows ---- 00 00 00 00 00 00 00 00 00 00 00 pvoid * __vbct_base2; Base2 address ---- virtual base class table, the following data ---- 00 00 00 00 04 00 00 00 08 00 00 00int i; int j;
Below is the assembly code of the F (Derived * PderiveD) function, analyzing other
29: void f (derived * pderived) 30: {0040C230 push ebp0040C231 mov ebp, esp0040C233 sub esp, 60h0040C236 push ebx0040C237 push esi0040C238 push edi0040C239 lea edi, [ebp-60h] 0040C23C mov ecx, 18h0040C241 mov eax, 0CCCCCCCCh0040C246 rep stos dword ptr [EDI] 31: MostBase1 * PBase1 = Pderived; 0040C248 CMP DWORD PTR [EBP 8], 0 [1] 0040C24C JNE F 27H (0040C257) 0040C24E MOV DWORD PTR [EBP-18H], 0 [2] 0040C255 JMP f 35H (0040C265) 0040C257 MOV EAX, DWORD PTR [EBP 8] 0040C25A MOV ECX, DWORD PTR [EAX] [3] 0040C25C MOV EDX, DWORD PTR [EBP 8] 0040C25F Add EDX, DWORD PTR [ECX 4] [4] 0040C262 MOV DWORD PTR [EBP-18H], EDX0040C265 MOV EAX, DWORD PTR [EBP-18H] 0040C268 MOV DWORD PTR [EBP-4], EAX [5] 32: MostBase2 * PBase2 = Pderived; 0040C26B CMP DWORD PTR [EBP 8], 00040 C26F JNE F 4AH (0040C27A) 0040C271 MOV DWORD PTR [EBP-1CH], 0 [6] 0040C278 JMP F 58H (0040C288) 0040C27A MOV ECX, DWORD PTR [EBP 8] 0040C27D MOV EDX, DWORD PTR [ECX] [7] 0040C27F MOV EAX, DWORD PTR [EBP 8] 0040C282 Add Eax, DWORD PTR [EDX 8] [8] 0040C285 MOV DWORD PTR [EBP-1CH], EAX0040C288 MOV ECX, DWORD PTR [EBP-1CH] 0040C28B MOV DWORD PTR [EBP-8], ECX33: Base1 * P1 = Pderived; 0040C28E MOV EDX, DWORD PTR [EBP 8] 0040C291 MOV DWORD PTR [EBP-0CH], EDX [9] 34: P1-> i = 1 ;
0040C294 MOV EAX, DWORD PTR [EBP-0CH] 0040C297 MOV ECX, DWORD PTR [EAX] 0040C299 MOV EDX, DWORD PTR [ECX 4] [10] 0040C29C MOV EAX, DWORD PTR [EBP-0CH] 0040C29F MOV DWORD PTR [ EAX EDX], 135: Base2 * P2 = Pderived; 0040C2A6 CMP DWORD PTR [EBP 8], 00040C2AA JE F 87H (0040C2B7) 0040C2AC MOV ECX, DWORD PTR [EBP 8] 0040C2AF Add ECX, 4 [11] 0040C2B2 MOV DWORD PTR [EBP-20H], ECX0040C2B5 JMP F 8EH (0040C2BE) 0040C2B7 MOV DWORD PTR [EBP-20H], 00040C2BE MOV EDX, DWORD PTR [EBP-20H] 0040C2C1 MOV DWORD PTR [EBP-10H], EDX [12] 36: P2-> J = 1; 0040C2C4 MOV EAX, DWORD PTR [EBP-10H] 0040C2C7 MOV ECX, DWORD PTR [EAX] 0040C2C9 MOV EDX, DWORD PTR [ECX 8] [13] 0040C2CC MOV EAX, DWORD PTR [EBP-10H] 0040C2CF MOV DWORD PTR [EAX EDX], 137: INT K = Pderived-> i; 0040C2D6 MOV ECX, DWO RD PTR [EBP 8] 0040C2D9 MOV EDX, DWORD PTR [ECX] 0040C2DB MOV EAX, DWORD PTR [EDX 4] [14] 0040C2DE MOV ECX, DWORD PTR [EBP 8] 0040C2E1 MOV EDX, DWORD PTR [ECX EAX] [15] 0040C2E4 MOV DWORD PTR [EBP-14H], EDX38: K = Pderived-> J; 0040C2E7 MOV EAX, DWORD PTR [EBP 8] 0040C2EA MOV ECX, DWORD PTR [EAX] 0040C2EC MOV EDX, DWORD PTR [ECX 8] [16] 0040C2EF MOV EAX, DWORD PTR [EBP 8] 0040C2F2 MOV ECX, DWORD PTR [EAX
edx] 0040C2F5 mov dword ptr [ebp-14h], ecx39: 40:} 0040C2F8 pop edi0040C2F9 pop esi0040C2FA pop ebx0040C2FB mov esp, ebp0040C2FD pop ebp0040C2FE ret [1] dword ptr [ebp 8h] is pderived, is not to look NULL. [2] DWORD PTR [EBP-18H] is an intermediate variable, when Pderived is NULL, it is also assigned to NULL [3] to remove __vbct_base1, its location is at the beginning of the Derived class [4] Remove the MostBast1 class Offset in Derived, this value is in the position of _vbct_base1 4, occupying 4 bytes, its value is 8, because Derived has two __vbct_prt, all 4 bytes, so MostBast1 is offset by Derived For 8. [5] assigning PBASE1, DWORD PTR [EBP-4] stores PBASE1; [6] is the same (2), but the address of the intermediate variable is different [7] is (3), remove __vbct_base1 [8] 4) Take out the offset of the MOSTBAST Class in Derived. At this time, it is 12 [9] to remove the address of the base1 in the DeriveD class, which is the address of __vbct_base1 in Derived, you may have questions, look at the following [10] P1 When you have data, or by __vbct_base1, you get the offset of MostBase1 in Derived by __vbct_base1, and finally get the address is Pderived 8 [11] Now remove the __vbct_base2 address, see Add Ecx, 4? [12] P2 assignment [13] to get the address of MostBase2 by __vbct_base2, then access J [14] to get the address [15] offset by __vbct_base1 [15] Offset in Eax, remove I [16] pass _ _vbct_base1 to get the address of MostBase2
The following is the C pseudo code I think, it may not be correct, because the assembly code has been optimized void f (Derived * Pderived) {---- MostBase1 * PBase1 = Pderived; MostBase1 * PBase1, * Temp1; if (PderiveD == 0) {TEMP1 = 0;} else {temp1 = (MostBase1 *) (PderiveD (Pderived -> __ vbct_base1 [1]));} PBASE1 = TEMP1;