`
dogasshole
  • 浏览: 842309 次
文章分类
社区版块
存档分类
最新评论

笔记:inside c++ object model

 
阅读更多

chap 1 object lessons

we have several coding style:

l procedure: for some algorithm, sth general, now these things are in the form of templates from time to time;

l abstract data type(ADT): class, public, private….

l object oriented: virtual and inheritance;

-----layout cost for adding encapsulation

comparing with c, normal c++’s class take the same size and efficiency with struct, no extra things.

the cost comes anything “virtual”----[virutal function],[virtual class]

1.1 the c++ object model

the model is:

l inside the object of the class: non-static data, include the pointer to the [virtual table];

l outside the object: static data, functions, virtual table;

l more: the virtual table and vptr is generated during the code generation process: constructor, assignment operator,

----adding inheritance:

for virtual class in multiple inheritance, we maintains a virtual table including base class, and pointer in object which points to the table;

----how the object effects the program

c++ object model adds lots of functions, so behind the c++ code, lots of things happens, a line of simple code can do so much things, that’s because the compiler do these for us, so we need to know what and why;

the compiler just modify the code, insert additional ones;

1.2 a keyword distinction

1.3 an object distinction

l the polymorphism is through the usage of pointer and reference: it’s about how to access the memory, oo is through the virtual talbe and the pointer to it, so we need this: interpretion of the memory and the actual calling of the function is independent, which pointer/reference can and direct object can’t;

l further: when we refer to a type A, we mean a set of type A’s sub-classes, what actually is depends on runtime;

l polymorphism forms: implicit new, virtual function calling, dynamic_cast;

l object size: [nonstatic data]+[padding/alignment]+[table/pointer for virtual];

----the type of a pointer

pointer: address+type, type----how the pointer inteprete the size and composition of the memory;

----adding polymorphism

oo is a higher level encapsulation----the types behind the interface;

at compile time, we only see the interface;

at runtime, it acts according to its real type;

and we pay for the cost of virtuals, we gain the elegant encapsulation and flexibility in design.

so it’s good when we gain design benefit ( and the benefit is what we need) on the cost of performance. so before we add virtual, the things should appear in our brain that: is this worth the cost;

------------------------------------------------------------------------------------------------------------

chap 2 The Semantics of Constructors

what’s the constructor’s task?----constructed the allocated memory;

how to construct, what’s included here?

l construct the object member----if the member has constructor, it should be constructed----with parameters explicitly, or just default constructor;

l leave the non-object member whatever: like int, bool, which will be intepreted according the content of the memory allocated;

l additional work: add vptr, vbtr and so on;

l order: fomr the beginning to the end----in every part of inheritance situation, is in the order of the member declaration; so use the member unconstructed yet to construct the previous member is not a good choice;

l member initialization list is the place to call member constructor, if the member need constructor to construct, there will always be one: we call explicily, or default call implicitly; when enter the body of constructor’s function, all the members have been constructed;

[case]

class base{

public:

base(){cout<<"base default"<<endl;

}

base(int i){cout<<"base int"<<endl;

}

};

class test{

public:

base t;

test(){

t=base(5);

}

};

int _tmain(int argc, _TCHAR* argv[])

{

test t;

return 0;

}

output:

base default

base int

default constructor is called before enter the function body, and the temp variable call base(int t) again;

l something can only appear at the member initialization list: reference, const members;

------------------------------------------------------------------------------------------------------------

Chapter 3 The Semantics of Data

The standard defines only limited part of c++, other parts depend on the compiler implementation;

Those implementations define what is stored in the object memory;

This chapter discusses those topics;

3.1 the binding of a data member

The situation comes from the fact that the class’ implementation always hires data outside the data, and the defensive programming requires us to put the data inside the object;

3.2 Data member layout

[standard]: within an access section, the data is ordered in the declaration order;

[implementation]:

l The access section order is compiler implementation dependent;

l The position of the additional data( such as vptr) is compiler implementation dependent;

3.3 Access of a Data Member

----Static Data Members

A single instance of each class static data member is stored in the data segment of the program;

&class_name::static_member==const member_type*;

----Nonstatic Data Members

l Store like c struct: one by one, reference with offset;

l The offset is known at compile time;

3.4 Inheritance and the Data Member

A derived class object is represented as the concatenation of its members with those of its base classes;

----Inheritance without Polymorphism

Just concatenate, no space and access time panelty;

When with multiple level inheritance, data alignment will cause more space taken;

----Adding polymorphism

Adding polymorphism add those things:

l Virtual table

l Pointer to virtual table in class object

l Augmentation of the constructor to initialize the object’s vptr to the right virtual table;

l Destructor: reset the vptr, which can be optimized;

----Multiple Inheritance

The case is becoming more and more complex, the essential remains the same;

The memory layout is still concatenate, so the pointer will be re-intepreted to the right place;

The compiler may reorder the class’ memory position for optimization;

----virtual inheritance

------------------------------------------------------------------------------------------------------------

chapter 4 The Semantics of Functions

in class we have 3 types of functions: static ,non-static, virtual

4.1 varieties of member invocation

----non static member function

l it’s transformed nonmember instance from member instance, pointer type* this is transformed to the function

l when we declare void class_name::member_function_name()const; it means[void class_name::member_function_name(const class_name* const this), it decorate the this pointer;[excellent]

l name mangling is hired

----virtual member functions

in c++ the function pointer is in 2 ways:

l point to the address;

l index of the virtual function table;

so the virtual function’s call will be transformed to like this:

ptr->normalize();è(*ptr->vptr[1])(ptr); [take ptr as the parameter]

----static member functions

l no this pointer will be transformed to as parameter: can’t access the non-static member directly

l stored in the global function space;

4.2 virtual member functions

virtual function table is generated for every class

each virtual function has fixed index in the vft of the base and the derived classes;

----Virtual Functions Under multiple Inheritance

l this pointer adjustment is needed: the memory layout intepretation

l the derived class’ object contain vptr for every parent: [pretty reasonable]

l [implementation]: use a thunk in assembly language to do the “this” pointer adjustment and jump to virtual pointer with vptr;

----virtual function under virtual inheritance

“this”pointer adjustmentàvirtual function table;

4.3 function effeciency

here we list the compiler’s work behind coder’s back:

l temp parameter: copy by value, assignment, these will mean constructors, destructors, assignment, and so on;

l the constructor of class with virtual functions means: vptr allocatd, which will cost some;

so the work behind the simple code maybe large,

keep clear,keep excellent;

4.4 pointer-to-member functions

----------------------------------------------------------------

struct _mptr{

int delta; //this pointer offset in multiple inheritance

int index; //<0: non-virtual function, >0: the index of the virtual function table;

union{

ptrtofunc faddr; //the real function pointer

int v_offset; //vptr’s offset from beginning;

};

};

----------------------------------------------------------------

then we have:

(ptr->*pmf)()------à

(pmf.index<0)

?//non virtual invocation

(*pmf.faddr)(ptr)

: // virtual invocation

(*ptr->vptr[pmf.index])(ptr);

4.5 inline functions

we need those notification of inline:

l inline do the work of encapsulation(info hiding) and also provide parameter checking and high efficiency;

l it work by code plug: may increase the code size, so use it when necessary;

l pay attention to the temp variable which my decrease the effeciency;

------------------------------------------------------------------------------------------------------------

chapter 5 Semantics of Construction, Destruction, and Copy

the essential things still fall into the memory, and its handling;

---class with pure virtual function need construtor if it has data, but it’s not recommended:

l [design reason]: pure virtual means interface, no data is better;

---derived class’s destructor is augmented to statically invoke each of its virtual base and immediate base class destructor; so if define the destructor as virtual, that’s nice, virtual destructor always take the index 0 of virtual function table, so the polymorphism will call the right destructor;

---Presence of Virtual Specification

mark with “virtual” only when necessary;

5.1 Object Construction without Inheritance

[life time]: a runtime attribute of an object, during its life time, the os will not retrieve its memory;

[internally declared]:

l default constructor, default destructor, default copy construtor, default copy aissgnment operator;

l so a simple c++ struct is very different at this point from c struct;

l the definition is triggered when needed, not always be defined;

----Abstract Data Type

initialization list is the process of calling constructor, so it’s the most efficient way;

----Preparing for Inheritance

virtual function will cause compiler driven augmentation:

l vptr: behind base class constructor, before the initialization list; also the vptr’s 4bytes space means huge cost in 3D modeling, so pay attention to the area with huge number of objects;

l the copy constructor and copy assignment: will be synthesized to handle the vptr, this case can’t be handled simply with bitwise copy;

5.2 Object Copy under Inheritance

[the constructor’s compiler driven augmentation]:

l make the member initialization list in the order of member declaration;

l member’s default construtor’s call

l vptr

l immediate class’ construtor calling in the order of their declaration;

l virtual base class’ construtor be called within the most deirved class;

[transform: member initialization]

Line::Line( const Point& begin, const point& end): _end(end),_begin(begin){}

transformed to

Line*

Line::Line(Line *this, const Point& begin, const point& end)

{

this->_begin.Point::Point(begin);// see? the constructor calling

this->_end.Point::Point(end);

return this;

}

// the member init list is the process calling constructor

---------------------------------------------------------------------

in copy construtor, self-copy guard is required;

----Virtual inheritance

[concept review]:

l virtual base class’ constructor is called at the most derived class’ construtor---that’s they are constructed when the complete class object is constructed, instead of during subobject construction;

l in multiple inheritance, the derived class contain multiple vptr every base class one;

l the vptr is set step by step, instead of set to the final at once;

l vptr is after base class’ construction before the init list;

[code]

---------------------------------------------------------------------

class base{

public:

base(){say();}

virtual void say(){cout<<"base"<<endl;}

};

class derive:public base{

public:

virtual void say(){cout<<"derive"<<endl;}

derive() {say();}

};

class derive2: public derive{

public:

virtual void say(){cout<<"derive2"<<endl;}

derive2(){say();}

};

int _tmain(int argc, _TCHAR* argv[])

{

base* p=new derive2;

return 0;

}

output:

base

derive

derive2

-------------------------------------------------------------------------------

so it’s pretty reasonable that when construtor the memory of the base class, the base class’ constructor is called, so the vptr is set to the base calss’ virtual function table, so the corresponding function is called;

5.3 object Copy Semantics

bitwise copy is not a copy constructor or an assignment operator,

it is ,en ,en just bitwise copy;

[synthesize situation]: any part of the memory need copy constructor(member, base class) or resolved(vptr,vbptr)

<no init list>: the init list is the process of calling construtor, and it’s not suitable to place it in the function body which will be like declaring new object, and for the copy constructor or copy assignment operator, it’s necessary to call the copy constructor/assignment and also ok to place them in the function body;

<vritual inheritance>: the copy constructor should be called at the most derived class, the synthesized copy constructor will do well, well the code-defined one may behave badly;

<solution>: make a init list like assinment list, put the derived class’ copy assignment at the last;

<recommentation>: don’t permit copy of virtual class, don’t put data in virtual class----member data, or virtual function which means the vptr;l

5.4 Object Efficiency

5.5 Semantics of Destruction

[synthesize/augmentation situation]: when part of the memory need destructed, even the coder define the destructor explicitly, it will be augmented to do the necessary job including calling the base class’ destructor;

[code situation/destructor symentics]: the work need to do at the end of the lifetime of the object;

[augmentation work]:like the constructor, in reverse order;

l reset vptr during the destruction of the base class

l …

[virtual inheritance consideration] provide 2 version of destructor:

l complete instance version

l serve as subobject version

------------------------------------------------------------------------------------------------------------

Chapter 6 Runtime Semantics

Lots of work is behind the coder’s back is done by c++ compiler;

------------------------------------------------------------------

class X,Y

target code: if(yy==xx.getValue())...

transformed code:

{

X temp1=xx.getValue();

Y temp2=yy.Operator Y();//type changing

int temp3=yy.operator==(temp2);//operator transformation

if(temp3)...

temp2.Y::~Y();

temp1.X::X();

}

So the simple code will be transformed to so much;

6.1 Object Construction and Destruction

Constructor at the object definition and destructor at the exit place are inserted;

So placing one object is not like what it looks like, it means the calling of constructor, so try to delay its definition;

----Global Object

[Data Zone]: all visible global objects are placed at program data segment;

static initialization and destructors are required;

----Local static object

its constructor is called at the first visit, like singleton implementation;

----Array of Objects

----Default Constructors and Destructors

6.2 Operators new and delete

delete :

if(pi!=0)

_delete(pi);

----semantics of new arrays

new: allocate memory + constructor

[array size]: the new_array function will store the number of elements of the array for “delete[]”

[derived object array problem]: for the delete, it’ll iterate the element base on the sizeof(element), which will result in mistake in polymorphism;

----semantics for placement operator new

the memory of the placement area shouldn’t be delete, which will result in being modified by the os;

[type] the placement area should be the same type or raw memory;

6.3 temp objects

class_name a=b+c;//no temp

a=b+c;//one temp, one assignment

will mean completely different things;

[lifetime]: temp object is destroyed at the last step in evaluating the full-expression that contains the point where they were created;the temp obj holding the result will persist until the object’s initialization;

------------------------------------------------------------------------------------------------------------

chapter 7 on the cupst of the object model

7.1 template

template have 2 parts:

l declaration: settle down the part don’t need type info

l instancing: settle down the part that need type info;

the combination of both form the final class definition;

[lazy-principle]: if it’s not used yet, leave it there;

if a member function which need type info is not used, it’s not instanced;

7.2 exception handling

try,throw,catch

[requirement work] destruct anything that need desctruction;

7.3 Runtime Type Identification

[virtual]: put class info into virtual table for dynamic_cast;

[efficiency]: info reference, comparison, more things;

----Reference

[exception] for reference can’t be referenced to NULL, so if dynamic_cast fails, it will throw exception;

----typeid operation

we have Typeid Operator and type_info related to it;

for:

l virtual: it’s decided at runtime

l nonvirtual: compile time;

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics