34
V V irtual Method irtual Method s s

Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

  • View
    217

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

VVirtual Methodirtual Methodss

Page 2: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

Why virtual methods?Why virtual methods?

Recall:Recall: In C++ with pointers and references to In C++ with pointers and references to objects there is automatic conversion:objects there is automatic conversion:

derived derived → → base.base. with such a pointer or reference with such a pointer or reference

only membersonly members (fields, methods)(fields, methods) declared in declared in basebase class class are accessibleare accessible

having the having the declareddeclared type of ptr/ref the compiler type of ptr/ref the compiler will always use the base class member, even if the will always use the base class member, even if the pointer points to an object of the derived class. pointer points to an object of the derived class.

Page 3: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

class pointclass point{{ int x,y;int x,y;  public:public: void show(); // draws a pointvoid show(); // draws a point void hide();void hide();};};class circle: public pointclass circle: public point{{ int r;int r;  public:public: void show(); // draws void show(); // draws circlecircle void hide();void hide();};};

circle o;circle o;point &rp=o;point &rp=o;rp.show(); rp.show(); // calls point::show// calls point::show

Page 4: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

Why virtual methods?Why virtual methods?

circle o;circle o;

point &rp=o;point &rp=o;

rp.show(); rp.show(); // // I want to call circleI want to call circle::show::show() !() !

How to achieve itHow to achieve it??

Page 5: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

class pointclass point{{ int x,y;int x,y;  public:public: char kind;char kind;   void show(); //draws pointvoid show(); //draws point   point(int x, int y)point(int x, int y) :x(x), y(y),:x(x), y(y), {{ kind=‘p’kind=‘p’;; }}};};

Solution is imperfectSolution is imperfect Ok., I’d say more: it is wrong!Ok., I’d say more: it is wrong! CompilerCompiler is ready to do it for us is ready to do it for us

class circle: public pointclass circle: public point{{ int r;int r;public:public: void show(); //draws void show(); //draws circlecircle circle(int x, int y, int r)circle(int x, int y, int r) :point(x,y), r(r):point(x,y), r(r) {{ kind='c'kind='c';; }}};};

circle o;circle o;point &rp=o;point &rp=o;if (rp.kind=='p')if (rp.kind=='p') rp.point::show(); rp.point::show(); elseelse rp.circle::show(); rp.circle::show();

Page 6: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

Virtual methodsVirtual methods If we declare a method as If we declare a method as virtualvirtual

when we call a virtual method by its namewhen we call a virtual method by its namethe compiler will use the method from proper class the compiler will use the method from proper class (the class of the actual object pointed to)(the class of the actual object pointed to), , not the method defined by the declared type o pointernot the method defined by the declared type o pointer..

void void virtualvirtual pointpoint::::hidehide();();

A method has to be declared A method has to be declared virtualvirtual in base class, in base class, in derived classes it will be virtual too, the keyword in derived classes it will be virtual too, the keyword virtualvirtual maymay but does not have to be used in but does not have to be used in derived classesderived classes

Page 7: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

class pointclass point

{{

int x,y;int x,y;

  

public:public:

void void virtualvirtual show(); show();

void void virtualvirtual hide(); hide();

};};

class circle: public pointclass circle: public point

{{

int r;int r;

  

public:public:

void show(); void show(); // virtual// virtual

void hide(); void hide(); // virtual// virtual

};};

Virtual methodsVirtual methods

Page 8: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

Virtual methods – how it works?Virtual methods – how it works? In the class where a virtual method will appear first, an In the class where a virtual method will appear first, an

additional hidden field will be added to each object — the additional hidden field will be added to each object — the address of virtual methods table (VMT).address of virtual methods table (VMT). The size of the object will grow. (see The size of the object will grow. (see →→ sizeofsizeof) )

For an object whose class cannot be determined with no doubt For an object whose class cannot be determined with no doubt at compile time, calls to methods declared virtual will be at compile time, calls to methods declared virtual will be indirectindirect (VMT will be used) (VMT will be used) It is slower thIt is slower thanan a direct ca a direct calll,l, virtual methodvirtual methods are not expanded s are not expanded inlineinline,, still it is quicker than implementing the effect manually (like above),still it is quicker than implementing the effect manually (like above), comcompilpiler does not make mistakeser does not make mistakes ( (errare humanum esterrare humanum est – – as you as you

knowknow).).

Page 9: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

Virtual methodsVirtual methods – how it works? – how it works? Calls by pointer and reference will be indirectCalls by pointer and reference will be indirect

Calls by object will be directCalls by object will be direct ... so quicker; in this case even virtual methods... so quicker; in this case even virtual methods may be may be

inline.inline.

NoteNote: : methods may be inherited and called for an methods may be inherited and called for an object of derived class, so calls to virtual methods object of derived class, so calls to virtual methods from within other methods are also indirectfrom within other methods are also indirect! !

Page 10: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

class pointclass point{{ int x,y;int x,y;  public:public: void virtual show(); void virtual show(); void virtual hide();void virtual hide(); void move(int dx, int dy)void move(int dx, int dy) {{ hide(); hide(); // virtual in point// virtual in point x+=dx;x+=dx; y+=dy;y+=dy; show(); show(); // virtual in point// virtual in point }}};};

class circle: public pointclass circle: public point{{ int r;int r;  public:public: void show(); void show(); void hide();void hide();};};  circle o;circle o;point &rp=o;point &rp=o;rp.show(); rp.show(); // calls circle::show()// calls circle::show()

rp.move(); rp.move(); ////inherited inherited point::move calls point::move calls //circle::show and circle::hide !!!//circle::show and circle::hide !!!

Page 11: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

PolymorphiPolymorphicc class class A class is called A class is called polymorpolymorphphicic if it contains at least if it contains at least

one one vvirtual metirtual methhodod

PPolymorphismolymorphism usage in practice: usage in practice: We declare a list of pointers to pointsWe declare a list of pointers to points ((polymorphipolymorphic classc class) )

– we put points, – we put points, circlescircles and and other figuresother figures on the list on the list.. Having a pointer we may tell each object to show itself Having a pointer we may tell each object to show itself

((indirect call to virtual show()indirect call to virtual show()), ), We may move figures with non-virtual We may move figures with non-virtual move()move(), but it will , but it will

call virtual call virtual show()show() and and hide()hide() properly properly. .

Page 12: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

Early and late bindingEarly and late binding

Early bindingEarly binding:: When a method is not virtual, or the class can be When a method is not virtual, or the class can be

unequivocalunequivocally determined at compile time, the ly determined at compile time, the method call is linked to the code (or the method is method call is linked to the code (or the method is expanded inline) at expanded inline) at linkinglinking stage stage..

Late bindingLate binding The proper virtual method is determined from The proper virtual method is determined from

actual type of the object at actual type of the object at runrun time time..

Page 13: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

Early and late bindingEarly and late binding

Non-virtual methods – always early bindingNon-virtual methods – always early binding

Virtual method not always is subject to late Virtual method not always is subject to late binding. It will be linked binding. It will be linked earlyearly if: if: We explicitly We explicitly use the use the class name and scope class name and scope

operator (::), operator (::), We call the method for direct object (neither a We call the method for direct object (neither a

pointer nor reference)pointer nor reference)..

Page 14: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

VVirtual irtual mmethodethodss

advantageadvantage:: applications easy to develop applications easy to develop , , Writing our code we may use methods that have Writing our code we may use methods that have

not been written yet!not been written yet! We do not have to copy the same code to many We do not have to copy the same code to many

different classes different classes ((see:see: move(move())). ). We do not risk to „enhance” the existing code with We do not risk to „enhance” the existing code with

new errorsnew errors..

Page 15: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

CConstructoronstructorss andand destructors destructors

CConstruonstrucctor tor may may notnot be virtual. be virtual.Anybody dares ask why?...Anybody dares ask why?...

DestruDestrucctor tor maymay and sometimes and sometimes shouldshould be be virtual (virtual (now whynow why?)?) NoteNote: : If we declare a destructor If we declare a destructor virtualvirtual, all his , all his

descendantdescendants – derived classes destructors – will s – derived classes destructors – will also be also be virtualvirtual ((do not bother that the names do not do not bother that the names do not match, it does not mattermatch, it does not matter).).

Page 16: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

Static Static andand virtual virtual

A static mA static metethhodod may may notnot be be vvirtualirtual.. Anybody dares ask why?... He will not be forgiven...Anybody dares ask why?... He will not be forgiven...

Page 17: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

VVirtual irtual mmethodethods inheritances inheritance

A vA virtualirtual method may be inherited method may be inherited It may be redefined; in its body a virtual method of base class It may be redefined; in its body a virtual method of base class

may be called.may be called.

exampleexample::

void void circlecircle::::showshow() ()

{{

pointpoint::::showshow(); // (); // draw the center of circledraw the center of circle

//// draw the circle draw the circle

}}

Page 18: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

Overloading and vOverloading and virtualirtualityity

Virtual methods have identical headers in all classes.Virtual methods have identical headers in all classes. The keyword The keyword virtualvirtual stands by the first declared. stands by the first declared. Other Other metmethhododss ( (overloaded with different parametersoverloaded with different parameters) ) are are

regular regular metmethhododss/operator/operators, are not virtuals, are not virtual

Example of non-virtual Example of non-virtual metmethhod: od:

void void pointpoint::::showshow(char * (char * descriptiondescription){...}; ){...};

Page 19: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

Friend and virtualFriend and virtual

VVirtualirtualityity isis independent from friendshipindependent from friendship. . Friend feature is not transitiveFriend feature is not transitive, , Friend access concerns only the method Friend access concerns only the method

(class::method)(class::method) which was declared friendwhich was declared friend,, A mA metethhodod redefined in derived class (no matter if redefined in derived class (no matter if

virtual) will not be automatically friendvirtual) will not be automatically friend..

Page 20: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

VVirtual irtual mmethodethods accessibilitys accessibility

Accessibility is determined at compile timeAccessibility is determined at compile time Pointer/reference Pointer/reference declareddeclared type decides type decides..

(like early binding – „early accessibility recognition”)(like early binding – „early accessibility recognition”)

Example: assume that all members of Example: assume that all members of circlecircle are are privateprivate::

circlecircle cc;;ppointoint &rp= &rp=cc;;rp.rp.showshow(); (); // OK – // OK – whywhy??

Page 21: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

AAbstrabstract classct class

AAbstrabstract classct class may not produce any objectsmay not produce any objects..

AAbstrabstract classct class is as a base class used to define is as a base class used to define a common „interface” – common features of a a common „interface” – common features of a family of family of descendantdescendant derived classes derived classes(example: (example: „figur„figuree””,, „ „numbernumber” ” ))

Abstract class inheritanceAbstract class inheritance

Page 22: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

Pure virtual methodPure virtual method

In In C++ C++ a class is abstract if it contains at least a class is abstract if it contains at least one one purepure vvirtual irtual method method – – a virtual without a a virtual without a bodybody. .

void virtual figurvoid virtual figuree::::drawdraw()=0;()=0;

Page 23: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

RTTIRTTI A pointer to base may be assigned the address to some A pointer to base may be assigned the address to some

descendant, therefore the descendant, therefore the declareddeclared pointer type does not fully pointer type does not fully determine the determine the actualactual class of the object referred to. class of the object referred to.

Sometimes at Sometimes at the the run time we would like to determine the run time we would like to determine the actual type of an object. If a polymorphic class is concerned, actual type of an object. If a polymorphic class is concerned, the object contains a special field that may be used to identify the object contains a special field that may be used to identify the class (it is a pointer to class’s VMT). With this field the the class (it is a pointer to class’s VMT). With this field the RTTI mechanism may determine types at run time. RTTI mechanism may determine types at run time.

If the pointer or reference refers to standard type or non-If the pointer or reference refers to standard type or non-polymorphic class, the type is determined according to polymorphic class, the type is determined according to declareddeclared type, and not the actual type of object – there is no type, and not the actual type of object – there is no other way to do it.other way to do it.

Page 24: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

RTTIRTTI

RTTI — RTTI — RunTime Type InformationRunTime Type Information

operator typeidoperator typeid

type_info typeid(arg)type_info typeid(arg)

arg: typarg: typee, , classclass, , variablevariable or objector object

Page 25: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

RTTIRTTI

class type_info class type_info {{ // // there’s there’s prprivateivate copy conscopy construtrucctor tor and and operatoroperator== // // there’s no way to make a copy of this object from outsidethere’s no way to make a copy of this object from outsidepublic:public: virtual ~type_info();virtual ~type_info(); bool operator==(const type_info& rhs) const;bool operator==(const type_info& rhs) const; bool operator!=(const type_info& rhs) const;bool operator!=(const type_info& rhs) const; bool before(const type_info& rhs) const; bool before(const type_info& rhs) const; const char* name() const;const char* name() const;};};

Page 26: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

RTTIRTTI

class A class A { { virtual void a(){}; virtual void a(){}; };};class B:public A {};class B:public A {};class C:public B {};class C:public B {};

A a, *pa;A a, *pa;C c;C c;pa=&c;pa=&c;

typeid(C)==typeid(pa)typeid(C)==typeid(pa) // 0// 0 typeid(a)==typeid(*pa)typeid(a)==typeid(*pa) // 0// 0 typeid(c)==typeid(*pa) typeid(c)==typeid(*pa) // 1// 1 typeid(B).name() typeid(B).name() // B// B typeid(pa).name() typeid(pa).name() // A *// A * typeid(*pa).name() typeid(*pa).name() // C// C typeid(A).before(typeid(*pa)) typeid(A).before(typeid(*pa)) // 1// 1 typeid(B).before(typeid(*pa)) typeid(B).before(typeid(*pa)) // 1// 1 typeid(C).before(typeid(*pa)) typeid(C).before(typeid(*pa)) // 0// 0 typeid(C).before(typeid(a)) typeid(C).before(typeid(a)) // 0 // 0

Page 27: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

*_cast*_castcast operators designed to replace C-style castcast operators designed to replace C-style cast

staticstatic_cast_cast << type-id type-id > > (( expression expression ))

dynamic_castdynamic_cast << type-id type-id > > (( expression expression ))

reinterpretreinterpret_cast_cast << type-id type-id > > (( expression expression ))

constconst_cast_cast << type-id type-id > > (( expression expression ))

these are opreators and 4 keywords of C++these are opreators and 4 keywords of C++ designed to allow greater compiler-level and controll and runtime designed to allow greater compiler-level and controll and runtime

controll of (error prone) castscontroll of (error prone) casts allow to experss programmer’s intentionsallow to experss programmer’s intentions

Page 28: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

staticstatic_cast_caststaticstatic_cast_cast << type-id type-id > > (( expression expression ))

cast based on types known at the compile-cast based on types known at the compile-timetime

unsafe as the C cast: (unsafe as the C cast: (type-idtype-id ))expressionexpression use with cautionuse with caution fastfast

no changing of const or volatile qualifiers of no changing of const or volatile qualifiers of experssionexperssion

Page 29: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

staticstatic_cast_caststaticstatic_cast_cast << type-id type-id > > (( expression expression ))

class A {};class A {};

class B:public Aclass B:public A{{

int method();int method();};};

int fun(A * pa)int fun(A * pa){{

static_cast<B*>(pa) -> method()static_cast<B*>(pa) -> method()// let’s hope pa points to B// let’s hope pa points to B

}}

Page 30: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

dynamicdynamic_cast_castdynamicdynamic_cast_cast << type-id type-id > > (( expression expression ))

cast based on RTTI, for use with pointers cast based on RTTI, for use with pointers and referencesand references

for pointers it returns NULL if for pointers it returns NULL if type-idtype-id is neither type is neither type of of expressionexpression nor nor experssion’s experssion’s parentparent

for references it throws exception if for references it throws exception if type-idtype-id is neither is neither type of type of expressionexpression nor nor experssion’s experssion’s parentparent

safe, but slowersafe, but slower no changing of const or volatile qualifiers of no changing of const or volatile qualifiers of

experssionexperssion

Page 31: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

dynamicdynamic_cast_castdynamicdynamic_cast_cast << type-id type-id > > (( expression expression ))

class A {};class A {};

class B:public Aclass B:public A{{};};

int fun()int fun(){{

A *pa, *aptr=new A;A *pa, *aptr=new A;B *pb, *bptr=new B;B *pb, *bptr=new B;......pa=dynamic_cast<A*>(bptr); pa=dynamic_cast<A*>(bptr); // OK// OKpb=dynamic_cast<B*>(aptr); pb=dynamic_cast<B*>(aptr); // NULL !!!// NULL !!!pb=dynamic_cast<B*>(pa); pb=dynamic_cast<B*>(pa); // OK// OK

}}

Page 32: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

reinterpretreinterpret_cast_cast

reinterpret_reinterpret_castcast << type-id type-id > > (( expression expression ))

cast based on types known at the compile-timecast based on types known at the compile-time used for address (pointer) arithmeticused for address (pointer) arithmetic use for pointers and integers (to let the compiler know Your use for pointers and integers (to let the compiler know Your

intence)intence) let Your boss think You’re a great guru of C++ programming let Your boss think You’re a great guru of C++ programming

;);)

CLASS *ptr;CLASS *ptr;...... unsigned int adress=reinterpret_cast<unsigned int>(ptr);unsigned int adress=reinterpret_cast<unsigned int>(ptr);

Page 33: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

constconst_cast_castconstconst_cast_cast << type-id type-id > > (( expression expression ))

cast based on types known at the compile-timecast based on types known at the compile-time use for pointers and referencesuse for pointers and references used for removing of const or volatile qualifiers of used for removing of const or volatile qualifiers of

experssionexperssion

class CLASSclass CLASS{{

int member;int member;

int CLASS::constmethod() constint CLASS::constmethod() const{{

const_cast<CLASS *>(this) -> member++;const_cast<CLASS *>(this) -> member++;// const_cast<int>(member)++; // const_cast<int>(member)++; ERRORERROR

}}}}

Page 34: Virtual Methods. Why virtual methods? Recall: In C++ with pointers and references to objects there is automatic conversion: derived → base. Recall: In

mutablemutable mutable keyword makes non-const non-static mutable keyword makes non-const non-static

member variable non-const in const member member variable non-const in const member functionsfunctions (similar to static_cast)(similar to static_cast)

class CLASSclass CLASS{{

mutable int member;mutable int member;

int CLASS::constmethod() constint CLASS::constmethod() const{{

member++; member++; // since member is mutable // since member is mutable }}

}}