C ++ object model notes

xiaoxiao2021-03-06  71

One of the C object model About object notes

Foreword

<< INSIDE THE C Object Model >> Stanley B.Lippman; Chinese version "Depth Exploration C Object Model" Houjie Translation. Seeing everyone thinks that it is a good book, so it will come from CHINAPUB. After reading it, I felt groggy, mainly very trivial, and this book was a bit outdated. In 2001, in 2001, the original English was probably between 1994 and 1998; the list of the List About compilation How to solve it, it is a bit a bit. Stanley B.Lippman has not seem to be in the line, and Houjie has corrected a lot of mistakes. However, Houjie style likes Chinese to take English habits. It is "Do you have Shopping today?"; There are many small scraping numbers in the book, and there are many nonsense in small scrapes. Chinese translated Chinese is very uncommon. The above aspects bring great inconvenience to reading and understanding, so this shark makes notes! !

Chapter 1 About Objects

1 C Object Model Stroustrup At first design C , the object model is derived from the simple object model and optimizes the memory space and access time, and the non-static data member is configured within each object in this model; Static data members, static member functions, non-static member functions are configured outside the object; the virtual function is also configured outside the object, and corresponds to the virtual function table (VBTL), and there is a virtual function table pointer in the object pointing Virtualistic table (VPTR), virtual function table first location is Object Type Information (RTTI)

Class Point

{

PUBLIC:

Point (Float XVAL);

Float x () const;

Static int pointcount ();

~ Point ();

Private:

Float x;

Static int pointcount;

}

Class Point

{

PUBLIC:

Point (Float XVAL);

Float x () const;

Static int pointcount ();

Virtual ~ Point ();

Virtual double x () const;

Private:

Float x;

Static int pointcount;

}

The object model after single inheritance, multi-inheritance, and virtual success is the header of the base class directly to the head of the derived class object. If it is a virtual base class, the pointer (BPTR) is used to point to the virtual base class.

2 C object size

By the size of its non-static data member; the amount of space is fill the space size of the memory; the amount of extra negative generation is generated inside. (Memory Alignment: Adjusting the size to a number of times, 4 multiples on 32-bit machines)

Independent class

Class Zoo

{

PUBLIC:

Zoo ();

Virtual ~ zoo ();

Virtual void rate ();

Private:

INT LOC

String name;

}

Main ()

{

ZOO ZA ("Zoey");

Zoo * pza = & za;

}

Single inheritance

Class Bear: Public Zoo

{

PUBLIC:

Bear ();

~ Bear ();

Void rtate ();

Virtual void Dance ();

Private:

ENUM DANCES {....

Dance Dances_know;

Int Cellblock;

}

Multiple inheritance and virtual succession are inherited. Note that the data member a with CHAR A is only one byte, and the memory is allowed to reinforce the base class in the later inheritance. That is to say, if there is CHAR B, C, D in the derived class, and 4 byte spaces are shared with the base class. C object model two construction statement notes

Constructor

Do you think this:

1. Any class If the default constructor is defined, the compiler will synthesize one;

2. Compiler synthesizes the default values ​​for each data member in the class;

The fact is not that, only the default constructor is synthesized when only the C compiler needs.

And do it in 4 cases.

The first case: a member of the object

Class a {......

Class B

{

Private:

A a a; // object member

INT X;

}

Synthetic constructor

B :: b ()

{

a.a :: a ();

}

If you define a constructor

A :: A ()

{

X = 0;

}

The compiler will append the code to the inside

A :: A ()

{

a.a :: a ();

X = 0;

}

The second case is the default constructor in the base class (including the synthesized)

As in the first one, you define a lot of constructor, the compiler will append the code to each constructor.

The third case with a virtual function class (including pure virtual functions)

The necessary operation of the compiler

1. A virtual function table will be generated, the address of the virtual function;

2. A virtual function pointer will be generated, pointing to the virtual function table address;

Therefore, the compiler sets the initial value of the VPTR for each object, place the appropriate virtual function table address, and add the code to the constructor defined by the class.

The fourth case is virtual inheritance

Class X {Publci: INT I;

Class A: PUBLIC Virtual X {public: Int J;

Class B: PUBLIC Virtual x {public: Double D;

Class C: Public A, Public B {public: int K;}

Void foo (const A * pa) {PA-> i = 1024;} // Unable to determine the location of PA-> x :: i in the compile period

Main () {foo (new a); foo (new c);} // may change to Void foo (const A * pa) {Pa -> _ vbcx-> i = 1024} VBCX is an object pointing to class x pointer, Of course, you must be determined in the constructor.

Copy constructor

Copy constructor: initialize the other object with an object. (The key is to initialize)

There are three cases that call the copy constructor

Class X {......};

X x; x xx = x // is not assigning operation but a copy constructor

Void foo (x x); // object parameters

FOOBAR () {x x; return x;} // Return to object

If the class does not provide a copy constructor, the compiler uses a bit number copy. That is to copy object data member values ​​to the other object, if you encounter object members, you will come in.

Class String

{public: // Category does not provide copy constructor displayed

Private:

Char * STR;

Int Len;

}

Class Word

{

Public: // Category does not provide a copy constructor displayed

Private:

Int accurs;

String str: // class contains object members

}

When the bit copy, the first position will copy int Occurs to encounter Word post to enter the Class String bit copy. When the compiler does not use the bit number copy, it generates a default copy constructor.

1. When the class contains an object member, while the latter's class declares a copy constructor (including programmers, compiler synthesis)

2. When the class inherits a base class, the latter exists when a copy constructor is functioning.

3. When class declares the virtual function

4. When class is derived from a inheritance chain

1. When the class contains an object member, while the latter is declared when a copy constructor is

Class String

{public:

String (const char *);

String (const string &) // class provides a copy constructor displayed

~ String ();

Private:

Char * STR;

Int Len;

}

Class Word

{

Public: // Category does not provide a copy constructor displayed

Private:

Int accurs;

String Str:

}

// will synthesize: Word :: Word (Const Word & WD) {str.string :: string (wd.str); occurs = wd.occurs;

2 When the class inherits a base class, the latter exists when a copy constructor is functioning.

Class Word: Public String

{

Public: // Category does not provide a copy constructor displayed

Private:

Int accurs;

String Str:

} // will synthesize one

3 When classes declare the virtual function

Class Word

{

Public: // Category does not provide a copy constructor displayed

Virtural cout (); // Class declared virtual function

Private:

Int accurs;

String Str:

} // The same reason is the same as the constructor, and the copy constructor is to process the virtual function pointer and the virtual function table.

4 When class is derived from a inheritance chain

Class Zoo {...}; Class Racconn: Public Virtual ZOO {....}; Class READPANDA: PUBLIC RACCONN {...};

At this time, it is not a class object to be an object to do initialization but the base class object is to be derived.

Raccoonn Rocky; Racconn Little = Rocky; // Simple bit number copies

Racpanda Littered; Racconnn Littecritter = Rocky;

// Simple bit number copies can not be done, the compiler must explicitly initialize the LitterCritter virtual successive pointer.

Three data member notes of C object model

First correct the first chapter about static members outside the object, the object is connected with a pointer, in fact, the object does not use the pointer to connect them, but through class access. The following is the empty class.

Class x {};

Class Y: public virtual x {};

LASS Z: PUBLIC Virtual X {};

Class A: public y, public z {};

Its size is x = 1 y = 4 z = 4 a = 8; the virtual success base class x Hosted 1 byte word The class of two objects have different addresses in memory.

Data member layout

Non-static data members are in the order of the alignment in class objects, as in the order of declarations, any intermediate intervening static data members will not put it. Each member in the same access section is not necessarily arranged, which is a higher address in the class object. The compiler may synthesize some internal data members to support the entire object model. The compiler combines multiple identical access.

Access of data

1 Static data member: In addition to the object, as a global variable, the accessibility of each subject will not lead to the burden of space and time. Point3D Origin, * Pt = & Origin

Origin.chunsize = 250;

Pt-> chunsize = 250;

Transformed inside to:

Point3d :: chunksize = 250; point3d :: chunksize = 250; whether object or pointer is the same.

If the static data member is called: foobar () .chunksize = 250; transformed into: (void) foobar (); Point3d :: chunksize = 250;

Take an address of a static data member to get a pointer to this data type instead of a pointer to its class member.

& Point3d :: chunksize; è const INT *

2 non-static data access

Want to access non-static data, the compiler needs to add the offset of the data member to the start address of the class object.

Origin.y = 0.9; è & Origin (& Point3D :: Y-1);

Virtuousness is more slower than other ways to access data members. When using objects and pointers to deliver virtual inheritance, the pointer access operation must be delayed during the execution period, and the object is fixed during the compile period.

Inheritance and data member

Things that are demonstrated in the C model, they are their own members of their base classes, and base class members always appear first, except for virtual success.

1 single inheritance: class Point3D single inherits in Point2D

2 single inheritance containing virtual functions: Point3D inherits in Point2D, Point2D has Virtual void foobar ();

3 inheritance: Point3D inherits in Point2D; Vertex3D inherits in Point3D and Vertex

4 virtual inheritance: Point3D Virtual Point2d; Vertex: Virtual Point2d; Vertex3d: Public Point3d, Public Vertex;

1 Each object will point more pointers to the virtual successor base class (Point2D);

2 Access time will increase at each inheritance, because adjustment of some pointers;

So there are two object models: one is to increase the pointer when the pointer is inherited; the other is to place the offset address of the virtual inheritance base in the virtual function table first bit value.

Object member efficiency

I use BCB5 under Sean A466 128SDRAM

Void __fastcall tform1 :: button1click (Tobject * Sender)

{// single variable

FLOAT PA_X, PB_X, PA_Y, PB_Y, PA_Z, PB_Z;

PA_X = 1.725; PA_Y = 0.875; PA_Z = 0.478; Pb_x = 0.315; PB_Y = 0.317; PB_Z = 0.838;

Long StartTime = gettickcount ();

For (int i = 0; i <10000000; i )

{

PB_X = PA_X-PB_Z;

PB_Y = PA_Y PB_X;

PB_Z = PA_Z PB_Y;

}

Long endtime = gettickcount ();

Label1-> CAPTION = endtime-starttime;

}

Void __fastcall tform1 :: button2click (Tobject * Sender)

{

Class Point3D

{

PUBLIC:

Point3d (float xx = 1.725, float yy = 0.838, float zz = 0.315): _X (xx), _ y (yy), _ z (zz) {}

FLOAT & X () {Return_x;}

Float & y () {return _y;

Float & z () {return_z;}

Private:

Float _x, _y, _z;

}

Point3D a, b;

Long StartTime = gettickcount ();

For (int i = 0; i <10000000; i )

{

B.X () = a.x () - b.z ();

B.Y () = a.y () b.x ();

B.Z () = a.z () B.Y ();

}

Long endtime = gettickcount ();

Label2-> CAPTION = endtime-starttime;

}

The remaining code is not given, everyone can do it, the object will not be very slow, the wondering structure is faster than a single variable?

Unopened

optimization

Single variable

0.530 (second)

0.521 (second)

Structural body

0.260 (second)

0.200 (second)

Array

0.531 (second)

0.521 (second)

Object

2.083 (second)

0.521 (second)

The book also made various inheritance test conclusions:

1 After the optimization is closed, the inline function is slow, so the programmer should actually test, do not judge the reasoning or common sense.

2 Sometimes optimization operations don't always run effectively.

3 The virtual success is disappointing after optimization.

Pointer to point to data

Class Point3D

{

PUBLIC:

Virtual ~ Point3d ();

protected:

Static Point3D Origin;

Float X, Y, Z;

}

Because VPTR accounts for 4 bytes of Float, the offset of VPTR placed on the head three data is 4, 8, 12; VPTR at the tail 0, 4, 8.

If you take the address of the data & point3d :: x Always 1 byte, why?

because

FLOAT POINT3D :: * p1 = 0;

FLOAT POINT3D :: * P2 = & POINT3D :: x;

IF (p1 == p2) // cannot distinguish, so you have to add one byte

And & Point3d :: x; and & Origin.z are different formerly the offset in the class, the latter gets a real memory address.

Pointing to a member's pointer efficiency

Unopened

optimization

Access directly

1.42

0.8

Pointer pointing to a binding member

3.04

0.8

Pointer pointing to the data member

5.34

0.8

Pointer to point to data

Unopened

optimization

Without inheritance

5.34

0.8

Single inheritance (three layers)

5.34

0.8

Musical inheritance (1 floor)

5.44

1.6

Deficiency inheritance (Layer 2)

5.51

2.4

Virtuousness It hinders optimization, introducing additional hierarchical indirectness in each layer

PB. * BX transformation into & Pb -> __ vbtr (bx-1) instead of & PB (bx-1)

Four member functions of C object model

Member function call mode

Non-static member functions: One of the C design guidelines is the same efficiency as the non-static member function is the same as the general non-member function.

Therefore, the compiler is chemically formed into a non-member function, and the step 1 rewrites the prototype of the function to add an additional parameter to the member function to provide an access pipe, so that the class object can call the function. This parameter is this pointer.

Point3d :: mangitude (point3d * const this);

2 Access each of the access operations to non-static data members to via the THIS pointer.

{RETURN SQR (this -> _ x * this -> _ x this -> _ y * this -> _ y this -> _ z * this -> _ z);

3 Retrieve the member function into an external function and make MANGLING processing on the function name.

Extern mangitude __7point3DFV (Regiester PionT3D * const this)

Virtual member function register float mag = magnitude (); èregister float mag = (* this-> vptr [2]) (this);

1 Compiler Generate a VPTR pointer; 2 index values ​​in the virtual function table; 3 is this pointer

Static member functions obj.magnitude (); ptr-> magnitude (); will be converted into magnitude__7point3dsfv ();

Virtual member function

If there is a virtual function in the class, there will be virtual function table pointer (vptr), the address, size and content of the table are compiled.

It is done when executed is to activate the virtual function at a specific virtual function table. The virtual function includes: 1 Deficit class rewritable base class virtual function, 2 inheriting the virtual function of the base class, 3 pure virtual functions.

Class Pont

{

PUBLIC:

Virtual ~ Point ();

Virtual Point & Mult (FLOAT) = 0;

Float x () const {return _x;}

Virtual float y () const {return 0;}

Virtual float x () const {return 0;}

Protecetd:

Point (float x = 0.0);

Float_x;

}

What happens when a class is derived from POINT?

1 Possible it inherits the function entity of the virtual function declared by the base class, which correctly said that the address of the function entity will be copied into the groove corresponding to the virtual function table of the derived class.

2 Maybe it can use your own function entity, who indicates that its own function entity address must be placed in the corresponding slot.

3 Maybe it can join a new virtual function table, this time the size of the virtual function table increases a slot, and the new function entity address is put into the slot.

Multiple inheritance

The complexity is around the base class in the second and subsequent base, and the THIS pointer must be adjusted when executed.

Class Base1 {

PUBLIC: BASE1 ();

Virtual ~ base1 ();

Virutal void Speckclearly (); Virutal Base1 * Clone () Const;

protected: float data_base1;

}

Class base2 {

PUBLIC: BASE1 ();

Virtual ~ base2 ();

Virutal void Mumble ();

Virutal Base1 * Clone () const;

protected: float data_base2;

}

Class Derived: Public Base1, Public Base2, PUBLIC BASE2

{

PUBLIC:

Derived ();

Virtual ~ derived ();

Virtual derived * clone () const;

Protected: float data_derive;

}

Base2 * pbase2 = new deerid;

è Adjustment: Derived * Temp = new derived; base2 * PBase2 = TEMP? Temp Sizeof (Base1): 0;

When the pointer of the second base class calls the virtual function of the derived class, the adjustment must be completed in the execution.也 OFFSET

THIS = Sizeof (base1);

Derived :: ~ derived (this);

The virtual function is under the virtual success

Class Point2d {

PUBLIC: POINT2D (float = 0.0, float = 0.0);

Virtual ~ Point2D ();

Virtual void mumble ();

Virtual float z ();

protected: float _x, _y;

}

Class Point3D: public virtual point2d {

Public: Point3d (float = 0.0, float = 0.0);

~ Point3D ();

Float z ();

protected: float_z;

}

Due to the object of Point2D and Point3D no longer match, the conversion between the two needs to adjust the THIS pointer.

Function efficiency

Unopened

optimization

Inline member

4.70

0.08

Friends function

6.13

4.43

Static member

6.13

4.43

Non-static member

6.13

4.43

Virtual function

6.90

4.76

Multi-inheritance

7.06

4.90

Virtual function

7.07

5.44

Pointer to the member function

Take the address of a non-static member function, if it is not a virtual function, it is obtained that the real address in memory. However, it is necessary to bind to an object address. Use a member function pointer, if it is not used for virtual functions, multiple inheritance, virtual success, etc., will not be higher than the general pointer.

Pointer to the virtual function

FLOAT (POINT:: * PMF) () = & point :: z; // Take the address of the virtual function gets the index value in the virtual function table

(* PTR-> VPTR [(int) PMF]) (PTR); // By calling it is converted into a single compilation period

Distinguishing PMF call is virtual function or non-virtual function method:

((int) PMF) & ~ 127)? (* PMF) (PTR): (* Ptrèvptr [(int) PMF] (PTR));

Pointer to multiple inheritance and virtual inheritance

Adopt structure

Struct_mptr

{

INT Delta; / / Indicates the this pointer offset

Int index;

Union {

PTRTOFUNC FADDR;

INT V_OFFSET; // virtual function in virtual function table index

}

}

(PTR-> * PMF) (); will become (PMF.Index <0)? (PMF.FADDR) (PTR): (PTR-> VPTR [PMF.index] (PTR));

Pointing the efficiency of the member function pointer

Unopened

optimization

Non-member function pointer

6.12

4.30

Member function pointer

6.38

4.30

Multiple inheritance non-virtual function pointer

6.32

4.30

Virtuous self-definition function pointer

6.84

4.70

Virtual function pointer

7.39

4.70

Multiple inheritance virtual function pointer

8.72

5.90

Musical inheritance function pointer

8.80

5.84

Inline function

In general, there are two stages of processing intraline function.

1 Analysis function definition to determine the inline capital of the function. If it is judged that it cannot be inserted, it will be converted to a static function.

2 Inline functions are in the call point, which will bring parameter evaluation and temporary object management.

Form parameters

Inline Int min (INT I, INT J) {RETURN I

Main ()

{

Int minval;

INT VAL1 = 1024;

INT VAL2 = 2048;

Minval = min (VAL1, VAL2);

Minval = min (1024, 2048);

Minval = min (foo (), bar () 1);

}

The first called minval = VAL1

Second call minval = 1024;

INT T1; INT T2; Minval = (T1 = FOO ()), (T1 = FOO ()), (T2 = BAR () 1) T1

Each form parameter is replaced by the actual parameters when Inline extension. If you can result in a multi-time value for actual parameters, you will introduce a temporary object.

Local variable

Inline Int min (Int i, int J)

{

INT minval = i

Return minVal;

}

Main ()

{INT LOVAL_VAR, MINVAL

Minval = min (VAL1, VAL2);

}

It will be expanded to:

{INT local_var, minval;

INT__MIN_LV_MINVAL;

Minval = (__min_lv_minval = var2), __min_lv_minval;

}

In general, each local variable in the inline function must be placed in a closed section of the function called, with a unique name.

If the inner function is extended multiple times, then a set of local variables each time. Separating multiple plays multiple times, then only a set of local variables can be reused.

The above is a plurality of similar object sharing member functions, each object is only different.

C object model five construct description assignment notes

1 Contact underheritance

Compile with C

Typedef struct

{

Float X, Y, Z;

Point}

The compiler will declare one: invalid default construct, invalid destructure, invalid copy, invalid assignment operation. However, they do not achieve them.

When you write a class, the volume has not changed.

Class Point

{

PUBLIC:

Point (flaot x = 0.0, float y = 0.0, float z = 0.0): _ x (x), _ y), _ z (z) {} // no construct, destructure, copy

Private:

Float _x, _y, _z;

}

Three disadvantages brought about by apparent initialization list

1. It is only valid when both the class members are PUBLIC.

2. You can only specify constants because they can be evaluated in the compilation period.

3. Since the compiler does not have automated implementation, the possibility of the failure of initialization behavior will be relatively high.

2 Prepare for inheritance

Class Point

{

PUBLIC:

Point (flaot x = 0.0, float y = 0.0): _ x (x), _ y (y) {}

// There is no construction, destructure, copy

Virtual float z ();

Private:

Float _x, _y;

}

The volume is a space of 4 bytes of VTBL, so many VPTRs.

1 The constructor is attached to the code to initialize the VPTR. Before being called by the base class constructor, it may be before the programmer writes.

Point * Point :: Point (point * this, float x, flaot y): _ x (x), _ y (y)

{

this -> _ vptr_point = _vtbl_point; // Initializing VPTR

this -> _ x = x; // Extension member initialization list

THIS -> _ Y = Y;

Return this;

}

2 synthesized a copy function and a copy assignment

Inline Point * Point :: Point (Point * this, Const Point & RHS)

{

this -> _ vptr_point = _vtbl_point;

Return this;

}

Assignment operation uses bit copy technology.

Construction under the inheritance system

Generally, the expansion operation made by the compiler is about the following

1. Record data members in the member initialization list, the initialization operation will be placed in the constructor itself to declare.

2. If a member does not appear in the initial list, it has a default constructor that will be called.

3. If there is VPtr in the class object, it will be set to the initial value, point to VBTL.

4. All upper layer base classes must be called to declare sequence.

1. If the base class is placed in the initial list, then any clearly specified parameters should be passed.

2. If the base class is not placed in the initial list, it has a default constructor will be called.

3. If the base class is the second or subsequent base class under multiple inheritance, the THIS pointer must be adjusted.

5. All virtual foundation constructors must be called, from left to right, from the most deep to the most:

1. If the class is placed in the initial list, then the parameters will pass, and there is no placement, and the class is constructed.

2. In addition, the offset of each virtual base sub-object in the class must be accessed during the execution period.

3. If the base class is the most underlying class, its constructs may be called, and some mechanisms will be put.

Class Point

{

PUBLIC:

Point (Flaot X = 0.0, Float y = 0.0)

Point (Const Point &); Point & Operator = (Const Point &);

Virtual ~ Point ();

Virtual float z () {return 0.0;}

Private:

Float _x, _y;

}

3 virtual success

Class Point3D: Public Virtual Point

{

PUBLIC:

Point3d (float x = 0.0, float y = 0.0, float z = 0.0): Point (x, y), _ z (z) {}

Point3D (Const Poin3D & RHS): Point (rhs), _ z (rhs.z) {}

~ Point3D ();

Point3D & Operator = (Const Point3D &);

Virtual float z () {return_z;}

protected:

Float_z;

}

Below is the content of Point3D constructor is expanded.

Point3D * Point3D :: Point3D (PionT3D * this, Bool _Most_derived, Float X, Float Y, Float Z)

{

IF (_MOST_DERIVED! = false) // The constructor of the virtual base class in C is responsible for call by the bottom layer, so it is necessary to judge that there is no sent this-> Point :: Point (x, y); // Decades that you have a derived class?

this -> _ vptr_point3d = _vtbl_point3d; // Initialize their own VPTR

this-> vptr_point3d_point = _vtbl_point3d_point; // Initialization base class VPTR

THIS -> _ z = rhs.z;

Return this;

}

4VPTR initialization

Class Vertex: Virtual Public Point {....

Class Vertex3d: Public Point3d, Public Vertex {... ..

Class PVERTEX: PUBLIC VERTEX3D {....

There are Virtual size () in them.

The construction of the constructor is: from the end, from the end, Calling the virtual function in the constructor is evaluated as a function of this class rather than the derived class, the polymorphism is invalid in the object structure.

1. The constructor of all the virtual base classes and the upper layer base class in the derived class is called.

2. The VPTR of the object after the above completion is initialized, pointing to VBTL

3. If there is a member initialized list, it will be expanded in the constructor, and must be performed after VPTR is set.

4. Finally, execute the code provided by the programmer.

PVERTEX :: PVERTEX (float x, float y, float z): _ next (0), Vertex3d (x, y, z), Point (x, y)

{

IF (Spyon)

CERR << "WITHIN PVERTEX :: PVERTEX ()" << "Size:" <, size () << endl;

}

Extension is:

PVERTEX * PVERTEX :: PVERTEX (PVERTEX * THIS, BOOL _MOT_DERIVED, FLOAT X, FLOAT, Y, FLOAT Z)

{

IF (_MOST_DERIVED! = FALSE)

This-> Point :: Point (x, y); this-> Vertex3d :: Vertex3D (x, y, z);

This -> _ vptr_pvertex = _vtbl_pvertex;

this -> _ vptr_point_pvertex = _vbtl_point_pvertex;

IF (Spyon)

CERR << "Withnin PVERTEX :: PVERTEX ()" << "Size:" << (* this -> _ vptr_pvertex [3] .faddr) (this) << ENDL;

Return this;

}

Object assignment

Assignment operations will need under the following conditions

1. When the class has an object member, and its class has an assignment operation.

2. When the base class of this class has an assignment operation.

3. When this class declares any virtual functions.

4. When this class is inherited from a virtual inheritance class, no matter whether the base class is assigned.

Inline Point & Point :: Operator = (Const Point & P)

{

_X = p._x;

_y = p._y;

Return this;

}

Class Point3D :: Virtual Public Point

{... ..}

The compiler will synthesize an assignment operation for Point3D

Inline Point3D & Point3d :: Operator = (Point3D * Const this, Const Point3D & P)

{

This-> Point :: Operator = (p);

_Z = p._z;

RETURN * THIS;

}

Because the C standard does not assign a list, the assignment of the base class will be repeatedly invoked by the derived class assignment.

Inline Vertex3d & Vertex3d :: Operator = (Const Vertex3D & V)

{

This-> Point :: Operator = (v);

This-> Point3d :: Operator = (v); // contains this-> Point :: Operator = (V);

This-> Vertex :: Operator = (v); // contains this-> Point :: Operator = (V);

Return this;

}

It is recommended that you do not allow an assignment operation of a virtual base class without claiming data in any virtual base class.

Object function

Construction and assignment of test objects

Struct Point3d {float x, y, z;};

Class Point3D {public: float x, y, z;};

optimization

Unopened

Structural body

5.84

7.22

Inline construction bitmap

6.00

7.33

Inline construction with virtual function

7.67

13.05

Single inheritance

6.26

7.33

Single inheritance inline definition

10.35

17.74

Single virtual inheritance within line

17.29

23.93

Multiple inheritance

6.26

7.33

Multiple inheritance within line

12.39

20.39

Multi-virtual inheritance within lineless

19.31

26.80

destruct

If the class does not define a patterned function, only the compiler will automatically synthesize only if the object member is members in the class and the object member has a destructor or the base class. Otherwise it is not required.

Class Point

{

PUBLIC:

Point (float x = 0.0, float y = 0.0);

Point (Const Point &);

Virtual float z (); ...

Private:

Float _x, _y;

}

Both Point Point has virtual functions, the compiler does not synthesize a destructor. Both LINES data members are Point Beguing, End; there is no need to do not have a destructor because Point itself has no destructor.

You should refuse to be called a symmetrical strategy: "You have defined constructs to define a descent."

Decide whether the class provides a descending function to see: Where is the class object life? What do you need to ensure the integrity of an object. This is also a key role in constructing and destructuring functions.

Main ()

{

Point Pt;

Point * p = new point3d;

FOO (& PT, P);

.

Delete P;

}

PT and P should be initialized before the function foo (), otherwise the user must clearly provide coordinates, and the usual use of users does not have a way to check if a local variable is initialized, so the constructor is working at this time. necessary. Also in the delete p, whether the integrity of the P-> x = 0 before the Delete P, such as: p-> x = 0; P-> Y = 0;

At present, one of the best strategies for sectors is to maintain two sectoral entities.

1 A complete object entity always sets VPTRS and calls the virtual basis destructor.

2 A base class sub-object entity unless a virtual function is called in the destructor, otherwise the destructor of the virtual base class will not be called and set VPTR.

When the life of an object is over, when the destructuring function begins to execute, since each base sectoral function is called, the derived class actually turns into a complete object. If the PVERTEX object is returned to the memory space, it will change to a Vertex3D, Vertex, Point3D, Point.

Destructure order:

1 The descent function itself is first implemented

2 If the class has a member object, the latter has a destructive function, then they will be called in the order in which the declaration is in.

3 If the object has a VPTR, it is now reset, pointing to the appropriate base class VTBL.

4 If there is any direct last layer of non-virtual basis having a destructive function, they will be called in the next order in the order of declaration.

5 If there is any virtual base class with a destructuring function, and the time that is the most late end, they will be called in the opposite order in the original order.

C object model six runtime notes

1 object constructor and sect

Place the statement of the object as much as possible near the program segment using it.

Foo ()

{

Point pointa; //

IF (cache)

Return 1; // This session is redundant, and it is wasteful

Pointa.run ()

RETURN 0; // The sector is also normal.

}

Foo ()

{

IF (cache)

Return 1; // will not

Point pointa; //

Pointa.run ()

RETURN 0; // The sector is also normal.

}

2 global object

The object that is not initialized is automatically initialized to zero. These global objects are initialized in front of the main program, and the global object will be automatically released before the program exits.

3 object arrays

Point Konts [10];

If the Point has a constructor and a destructive function, the turntable or sector each object will be destructed. If there is a virtual base class, it will construct a VEC_VNEW () to construct a VEC_NEW ().

Void * vec_new (void * array, size_t elem_size, int elem_count, void (* constructor) (VOID * CHAR)

Void * vec_delete (void * array, size_t elem_size, int elem_count, void (* destructure) (void *, char); Point Konts [10];

VEC_NEW (& Kontes, Sieof (Point), 10, & Point :: Point, 0);

If: Point Konts [10] = {POINT (), Point (1.0, 1.0, 0.5), - 1.0};

For those who obviously get initial values, Vec_new is no longer necessary, but there is still necessary for VEC_NEW that is not initialized.

4 new and delete

INT * PI = New Int (5);

DELETE PI;

Change to:

INT * PI;

IF (pi = _new (sizeof (int)))

* pi = 5;

IF (pi! = 0)

_Delete (pi);

If it is an object

Point3d * Orgin = new point3d; è if (Origin = _new (sizeof (pointof (Point3D))) Origin = Point3D :: Pointed (Origin);

Abnormally:

IF (Origin = _new (Sizeof (Point3D))))

{Try {Origin = Point3D :: Point3D (Origin);

Catch (...) {_delete (Origin); throw;}

}

DELETE Origin; è if (Origin! = 0) {Point3D :: ~ Point3d (Origin); _Delete (Origin);

Array New

INT * p_Array = new int [5]; è int * p_Array = (int *) _ new (5 * sizeof (int));

If it is not a class object, or if the class object does not construct a function, VEC_NEW does not call, just simply obtain the release memory.

Point3D * p_Array = new point3d [10]; è

POINT3D * P_Array;

P_Array = VEC_NEW (0, Sizeof (Point3D), 10, & Point3D :: Point3d, & Point3D :: ~ PionT3D);

Pre-defined overloaded New

Void * Operator new (size_t, void * p) {return p;

Call: Point * PTW = New (Arena) Pont; // where Arena is a block pointing to memory.

è point * ptw = (point *) ARENA; if (ptw! = 0) PTW-> Point :: Point ();

The true pointer type of Arena, must point to the same type of class, or it is a fresh memory, enough to accommodate this type of object.

Dead is obviously not supported.

Fresh memory is configured: char * arena = new char [sizeof (point);

Objects of the same type can be obtained: Point * arena = new point;

In any case, the storage space of the new PONT is indeed covered in Arena. In general, the pre-defined overloaded NEW does not support polymorphism.

5 Temporary object

C standard allows the compiler to have a complete freedom for the production of temporary objects

The destroyable of the temporary object should be the last step in the full expression of the full expression. This complete expression causes a temporary object.

String v = S A B C; Temporary objects are: temp1 = s a; temp2 = temp1 b; Temp3 = Temp2 C; Temporary object 1, the temporary object 1 is not used, but Wait until the entire expression is completed, the memory can be released. Any temporary object containing the expression execution result should be kept until the object's initialization operation is completed.

The above expression produces three temporary objects, after the end of the expression, TEMP1, TEMP2 will be released, and TEMP3 is allowed to be released after V = TEMP3.

If a temporary object is bound to a reference, the object will remain until the end of the life of the initialization reference is ended, or the end of the temporary object is ending ----- What is the case to see

Const string & space = a b; the temporary object here will end with the Space, or more than the range of life.

Const string & s = foo (); // point foo () {Return Point;} The temporary object here is more than the range of life. S will be wrong

This strip does not make a clear explanation of the pointer binding temporary object

Const char * a = B C D;

C object model seven template abnormal RTTI notes

The following three questions about the template:

1 What happens when a template statement?

2 Instantiate the inline member

3 How to instantiate a member, a template member function, a template static member.

Template

Class Point

{

PUBLIC:

Enum status {UNALLOCATED, NORMALIZED};

POINT (T x = 0.0, T y = 0.0, T Z = 0.0);

~ Point ();

Void * Operator new (SIZE_T);

void * Opertaor deleted (vide *, size_t);

Private:

Static Point * freeelist;

Static int chunsize;

T _x, _y, _z;

}

When the compiler sees the template class declaration, it does not have, the above static data member, nested enumeration is not available. Although the true type of Enum Status is the same in all Point instances. But they must pass templates An instance of the Point class to access and operate.

Point :: status s; // ok

Point :: status s; // error

Pointer: const point * ptr = 0; not instantiated;

Quote: const point & ref = 0; will instantiate

è Point Temp (FLOA T (0)); const point & ref = TEMP;

Template error report: All syntax errors are detected, but do not do type checks.

Template name solution

Extern double foo (double); // class S definition

Template

Class S

{

PUBLIC:

Void invariant () {member = foo (val);

T dependent () {return foo (member);

Private:

Int Val;

T member;

}

EXTREN INT FOO (int);

S S1;

S1.INVARIANT ();

S1.dependent ();

The use of the resolution of the member name in the template is determined according to this name and "related to the parameter type used to instantiate the template" in accordance with the use of "parameter type of the template", which is not resolved, and the use of instantiated parameter types So: S1.INVARIANT (); foo called EXTERN DOUBLE FOO (Double); void invariant () {met = foo (val);} is Int Val; type is independent. And S1.Dependent ); Foo called Extern Int foo (int); because of T Dependent () {Return Foo (Member);} is the T MEMBER; type is related.

Instantiation of member functions

The C standard is only instantiated after the member function is used. But it is not accurate to follow. Willing as follows:

1 Space and time considerations. If there are 100 member functions in the class, your program is only for some types of functions, then other 193 functions will be instantiated will cost a lot of time and space.

2 The mechanism that has not been implemented is not a template instantiated all types that must fully support all operators needed for a set of member functions.

Point * ptr = new point ;

Used Void * Operator New (SIZE_T); POINT (T x = 0.0, T y = 0.0, T Z = 0.0);

At present, there are two strategies in the compiler: 1 is that the compile time program code must be prepared in the program text file, 2 is the tool boot compiler instantiated behavior when connecting.

1 How do the compiler find out the definition of a function?

1 is included in the template program text, 2 requires a file naming rule.

2 How do the compiler only instantiate the members used in the program?

1 Ignore, produce all the members functions of an instantiated class. 2 Simulation connection operation: Which function is really needed.

3 How does the compiler prevent member definitions from being instantiated in multiple OBJ files?

1 Generate a plurality of instances leaving only one at the connection. 2 By the user to boot the "Simulation Connection Phase" instance.

Borland supports the first middle method of all issues.

Abnormal processing

In general, the abnormal handling mechanism needs to be precisely cooperated with a data structure generated by the compiler and an exception library in the execution period.

Compiler makes selection in terms of program speed and size

1 In order to maintain a running speed, the compiler can establish a data structure for the compilation period. However, the compiler can ignore these structures until an abnormality

2 In order to maintain the size of the program, the compiler can establish the data structure used during the execution period, but the compiler only establishes the data structure when necessary.

Exceptions can be divided into multiple areas: Try Block and the TRY block and the entire area.

Void Mumble (Void * arena)

{

Point * p = new point;

Try

{

SMLOCK (ARENA);

}

Catch (...)

{

Smunlock (Arena);

Delete P;

Throw;

}

Smunlock (Arena);

Delete P;

}

Why doesn't Point * p = new point; is not within Try Block? Because there is nothing to release before. Although it will throw an exception, it will handle the problem of resource release.

Support an exception to complicate the constructor of the member object or base sub-object class. For example: class x member objects A, B, C. They all have a pair of constructors and destructor. But a constructor throws Abnormal, then the sectors of A, B, and C do not need to be called. But the constructor of B throws an exception, then a destructor is called, and the descents of C do not call. The same is POINT3D * PTR = New Point3D [512] If the 100 element throws an abnormality, then the first 99 will call the descent, and the following will not be called.

When an exception occurs, the compiler is to complete the following:

1 Test the THROW operation function

2 Decide whether the throw operation occurs in the TRY area

2.1 If the compiler puts an exception type and each Catch comparison

2.2 If the process control is comparable, the process control is handed over to Catch 3 If the Throw operation does not occur in the TRY area or there is no Catch anastomosis, then the system will do 1 release all local existing objects, 2 from the stack to open the current function exhibition 3 Perform the next function in the program stack, then repeat 2-3

Deciding whether the Throw operation occurred in the TRY area to generate regional statistics

If the compiler will use the type descriptor (RTTI) using the exception type and each Catch comparison system (RTTI)

When an exception is thrown out, an exception object is placed in the same form of anomalous data stack, passed from Throw to a Catch is an exception object address and a type descriptor. General Catch (ex & p) basically adopted if it is an object, Can cut.

Object size

No abnormalities

Abnormal

percentage

Borland

86.822

89.510

3%

Microsoft

60.146

67.071

13%

Symantec

69.786

74.826

8%

Execution speed

Borland

78

83

6%

Microsoft

83

87

5%

Symantec

94

96

4%

Operation Type Identification (RTTI)

Back down:

RTTI is later introduced and does not use a new keyword, but if the declared virtual function will have RTTI.

Dynamic Type Conversion: Dynamic_cast can determine the type in the running period. If successful will pass back the pointer, 0 is more expensive than static conversion cost, but it is safe. Dynamic_cast (& PT) If it is a reference to fail, it is BAD_CAST exception.

TypeID:

Use it to achieve the purpose of reference

IF (TypeID (RT) == TypeId (FCT))

FCT & RF = static_cast (rf);

TypeID transfer CONST reference type is type_info: BOOL TYPE_INFO :: Operator == (const type_info &) cosnt;

Class Type_info

{

PUBLIC:

Virtual ~ Type_info ();

Bool Operator == (const type_info).

BOOL Operator! = (const type_info) const;

BOOL Before (const type_info "

Const char * name () const;

Private:

TYPE_INFO (const type_infor);

TYPE_INFO & OPERATOR = (const type_info);

}

RTTI is suitable for the common class and general types with polymorphism Type.

Author: dark shark has husbandry completion time: 2003-7-26,27,29,8-3,16,18,19 http://blog.9cbs.net/ZengMuAnSha

转载请注明原文地址:https://www.9cbs.com/read-106799.html

New Post(0)