(Don't see if you don't have this book)
The last time I saw this book is a year ago (it's the traditional version of Mr.), I spent a week after reading, swallowing the date, I don't want to understand, so, I also solved my many doubts in C , this time I finally saw the Simplified Edition, I also spent a week, maybe it's really a life, two cooked (or the intimate sense of Simplified text ^ _ ^), thinking about the problem while discovering some problems, a fool See you, not spit.
One of the snakes, P84,
Class x {};
Class Y: public virtual x {};
Class Z: Public Virtual Z {};
Class A: Public X, Pubic Z {};
Written in the book
In fact, this size is affected by three factors.
1) The extra burden caused by the language itself.
2) The compiler is the optimization process of the arch in special circumstances. .
3) ALIGNMENT limit. .
Mr. Mr. you add itself as follows:
At that time, I saw this picture is really "Best I have to solve", no matter how Y or Z has been inherited from X Virtual, there is an extra 4byte overhead, that is, it is not an Empty Class, that 1 char Byte for y (z) IS Empty does not say, and it is true from lippman.
"2) Compiler For the optimization processing provided by special circumstances, the 1by SubObject of Virtual Base Class X also appears on Class Y and Z, which is traditionally placed in the end of the Derived Class's fixed (no) section," The P88 is explained, "it stores the data directly in each Class Object, which is the case for inherited NonStatic Data Member (regardless of Virtual or Nonvirtual Base Class",
Therefore, I understand the figure should be like this:
That is, the members in the parent class are directly inherited into subclasses, but for virtual inheritance, it is necessary to access through a indirect layer (representative of some form of pointers), this idea is in Section 3.5 ( The virtual inheritance is once again verified, (see P121), the book also mentioned that the optimization of Empty Base Class usually places the Empty Base Class at the beginning of the Derived Class Object, so that no additional space is not taken. From this, it can also be analyzed that A is as follows: (in this book, Mr. Wait did not give this picture)
SIZEOF (a) is 12 Byte, and in the case of Empty Base Class, it is 8 BYTE.
The second, P234,
Mr. Wait, changed the order of lippman (what happened during the design of the structure), his basis "This is in line with the opposite order of the CTOR", this is not too subjective, too obeying the word, I don't see Lippman said "2 The Dtor's function itself is now executed, that is, VPTR will be reset before execution of programmers ", in fact.
Struct b {};
Struct D1: Virtual public b {};
Struct D2: Virtual public b {}; struct d: public D1, d2 {};
The CTOR is as follows: (can refer to Vertex3D CTOR)
D () {if (__most_derived) THIS-> B ();
THIS-> D1 (False), this-> D2 (false);
VPTR = D :: vptr; // usercode}
File: // The compiler is expanded, as follows, in the reverse order. ~ d () {vptr = d :: vptr; // ** //// user code ...
THIS-> ~ D2 (FALSE), this ~ D1 (false); if (__most_derived) THIS-> ~ B ();
}
Isn't this the meaning of lippman (see the order from 1 to 5 in the book)? Mr. Mr. said that the opposite of the custom order is difficult to understand.
When D is destructed, set vptr = d :: vptr, then perform a destructive correspondence, then set up D2 :: VPTR, D1 :: VPTR, last B :: VPTR, these are easy to understand.
At the 3rd point of Mr., "If the Object has a VPTR, it is now reset, pointing to the appropriate base class Virtual Table", that is, the setting of VPTR is jumped, is in ~ d () User code is executed (// ** // tag is not executed), set the VPTR to D2 :: VPTR, then execute ~ D2 () function body, and finally set VPTR at the end of ~ D2 () D1 :: vptr, execute ~ d1 (), odd!
This is a VPTR that sets VPTR to another unrelated class, but there is no mother and child relationship between them. Personally think that the order of Mr. Wait is too theoretical, and the method of lippman is actually starting.
Snaked 3: P263
Class Point
{
PUBLIC:
Virtual ~ Point () {}
}
Class Point3D: Public Point
{
}
Point * ptr = new point3d [10];
For (int = 0; ix { POINT * P = & ((Point3D *) PTR) [ix]; Delete P; } Mr. Wait will change to: For (int = 0; ix { POINT3D * P = & (POINT3D *) PTR) [ix]; Delete P; } This is obvious that the virtual parsing function is not used to specify the oblivalent type, even if the specified type is the resolve (P-> VPTR [1]) (P), which does not have improved performance. Finally, point out that Lippman believes Point * ptr = new point3d [10]; DELETE [] PTR; "This is not a good idea (see P263), maybe it is not ^ _ ^, but I am completely correct, so everyone can rest assured that I can use it at the test results of my VC6. (I didn't test other compilers, I can try it yourself).