virtual functions and dynamic polymorphism

39

Upload: judd

Post on 12-Jan-2016

47 views

Category:

Documents


2 download

DESCRIPTION

VIRTUAL FUNCTIONS AND DYNAMIC POLYMORPHISM. Polymorphism refers to the property by which objects belonging to different classes are able to respond to the same message, but in different forms. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM
Page 2: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

Polymorphism refers to the property by which objects belonging to different classes are able to respond to the same message, but in different forms.

An essential requirement of polymorphism is the ability to refer to the objects without any regard to their classes.

Therefore a single pointer is used to refer to the objects of different classes.

The compiler simply ignores the contents of the pointer and chooses the member function that matches the type of the pointer

Page 3: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

long int factorialsum(int a , int b){ int I;long int sum;for(sum=0,i=a;i<=b;i++)sum+=factorial(i);return sum; }

long int cubesum(int a , int b){ int I;long int sum;for(sum=0,i=a;i<=b;i++)sum+=cube(i);return sum; }

Page 4: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

long int generatesum(int a , int b, long int (*p)()){ int I;long int sum;for(sum=0,i=a;i<=b;i++)sum+=(*p)(i);return sum; }

We call this function by passing the functions whose returned values have to be the summed up as the last parameter to this generic function.

X=generatesum(1,5,factorial);X= geneatesum(2.3.cube);

Page 5: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

(*p)(i) exhibits polymorphic behavior, because while compiling it, it is not known which functions will actually be executed.

It becomes apparent only when the client program that calls this generic function is compiled.

Page 6: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

class A{ public: void show() { cout<<"A";} };

class B:public A{ public: void show()

{ A::show(); cout<<"B"; } };

void main(){ B B1;

A A1;A *Aptr; Aptr=&A1; Aptr->show(); Aptr=&B1; Aptr->show();

}

Page 7: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

Output :AA

The compiler decides which function to call by considering the type of the pointer, the type of the object pointed at by the pointer is not considered.

In such cases, Overriding becomes ineffective!

Page 8: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

class A{ public: void show() { cout<<“A”; } };

class B:public A{ public: void show() { A::show(); cout<<“B”; } };

void main(){ B B1;

A A1;A &Aref1=A1; Aref1.show(); A &Aref2=B1;Aref2.show();

}

Output :AA

Page 9: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

Provides the feature of Dynamic Polymorphism.

When a function is made virtual, C++ determines which function to use at run time based on the type of object pointed to by the base pointer, rather than the type of the pointer (late binding).

Thus, by making the base pointer point to different objects, different versions of the virtual function can be executed.

Page 10: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

How do you declare a function as virtual? The prototype of the function within the class should be prefixed with the virtual keyword.

It may appear before or after the keyword specifying the return type of the function.

If defined outside the class, only function prototype needs to have virtual keyword.

class A { public: virtual void show();};class A { public: void virtual show();};

Page 11: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

class A{ public: virtual void show();

};class B:public A{ public: void show(); };void B::show() { A::show(); cout<<"B"; }void A::show() { cout<<"A"; }

void main(){ B B1;

A A1;A *Aptr; Aptr=&A1; Aptr->show(); Aptr=&B1; Aptr->show();

}

Page 12: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

When the base class pointer points at an object of the derived class and a call is dispatched to an overridden virtual function, then it is the overriding function of the derived class that is called.( and not the overridden function in the base class)

Virtual Functions of the base class reappear as virtual in the derived class as well.

(using the keyword virtual while defining the overriding derived class function is optional )

Page 13: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

class A{ public: virtual void show()//A::show() is virtual {cout<<“A”<<endl; } };class B:public A{ public: void show();

{cout<<“B”<<endl;} }; //B::show() is virtualclass C:public B{ public: void show() {cout<<“C”<<endl;} }; //C::show() is virtual

Page 14: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

void main(){B *Bptr;Bptr= new C;Bptr->show();}

Output : C

Page 15: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

Run time polymorphism is achieved only when a virtual function is accessed through a pointer to the base class.

It cannot be achieved using the object name along with the dot operator to access virtual function.

Page 16: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

The Mechanism of Virtual Functions: For every base class with virtual functions, a

table of function addresses is created during runtime.(VTBL or Virtual Table)

This table contains the address of every virtual function that has been declared in the corresponding class.

Eg:class A{ public:

virtual void abc();virtual void def();

};

Page 17: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

During runtime, the VBTL of class A will be:

Such a table of addresses of virtual functions will be created for the derived class as well.

If the derived class does not redefine a certain base class virtual member, the table will contain the address of the inherited base class virtual function itself. ( else the table will contain the address of the overriding function.)

101 201

Address of A::abc()

Address of A::def()

Page 18: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

class B: public A{ public:

void def();void virtual ghi();

};The VBTL for class B appears as:

101 301

Address of A::abc()

Address of B::def()

401

Address of B::ghi()

Page 19: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

Every object of a class has a virtual function containing a pointer called a Virtual pointer or VPTR to the VTBL of the corresponding class.

Whenever a call is dispatched to a virtual function( through an object or reference to an object or pointer to an object), then the first of all the values of the VPTR of the object is read.

The address of the called function from the corresponding VTBL is obtained and called.

Page 20: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

The table size varies from class to class. The size of the objects of the classes with

virtual functions increases uniformly due to the presence of VPTR.

Why not declare functions virtual by default? They incur a runtime cost in the form of

space that is wasted for creating the VTBL and embedding the VPTR in each and every object of the base/derived class.

Time is also lost in searching the VTBL for the function address.

Page 21: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

Pure Virtual Functions The virtual function is seldom used for

performing any task is generally used as a placeholder.

A do-nothing function may be defined as:virtual <r_type> <f_name> (<formal_args>)

=0;Such a function is a pure virtual function.

A pure virtual function is a function declared in a base class that has no definition relative to the base class.

In such cases, the compiler requires it to either define the function or redeclares it

as a pure virtual function.

Page 22: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

#include<iostream.h>class number{ protected : int val ; public : void setVal (int i ){ val = i ; } virtual void show () = 0 ; };class hexType : public number{ public : void show () { cout<<hex<<val<<“\n” ; } };class decType : public number{ public : void show () { cout<<val<<“\n” ; } };

Page 23: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

class octType : public number{ public : void show () { cout<<oct<<val<<“\n” ; } };int main(){ decType d; hexType h; octType o ; d.setVal(20); d.show(); // displays 20 decimal h.setVal(20); h.show(); // displays 14 hex o.setVal(20); o.show(); // displays 24 decimal return 0; } When a virtual function is declared as pure, all

derived classes must override it. If a derived class fails, a compile-time error will result.

Page 24: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

A class containing a pure virtual function cannot be used to declare any objects of its own and are called ABSTRACT BASE CLASSES.

An ABC can not be instantiated, that is, the object of an ABC can not be declared.

What is the purpose of an Abstract Base Class? It is used to provide some traits to the

derived classes. It is used as an interface

To create a base pointer required for achieving run time polymorphism.

Page 25: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

Any class that derives from an ABC must override all pure virtual functions in the base class or it gets branded as an ABC by the compiler.

ABC are also used to build implementation in stages. If a pure virtual function inherited from the base class is not defined in the derived class, it remains a pure virtual function in the derived class. Thus, the derived class also becomes an abstract class.

If there is no concrete definition of few of the virtual functions of the base class, with respect to that derived class, then they will be left undefined and that class will become ABC for the further derived classes.

Page 26: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

class A {public: void virtual abc()=0;void virtual def()=0;void virtual ghi()=0;};

void main(){ A A1; //error}

Page 27: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

class B: public A{public: void abc()

{ //deftn of abc}};void main(){B B1; //error}

Page 28: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

class C: public B{public: void def(){ // deftn of def }void ghi(){//deftn of ghi}};void main(){C C1; //OK}

Page 29: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

class A{ public: void virtual abc()=0; };void A::abc() // pure virtual fn defined{//defn of A::abc}

class B:public A{ public: void abc(); };void B::abc(){ A::abc(); // derived class invokes that

function //thro scope resolution operator //defn of rest of B::abc() } //defining a pure virtual function in the abstract base class itself

Page 30: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

The ability to provide an implementation to a pure virtual function allows data types to provide core functionalities while still requiring the derived classes to provide specialized implementations.

The class remains abstract even if we provide an implementation for its pure virtual function.

As per requirement, a member function can be non-virtual, virtual or pure virtual.

Page 31: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

Virtual Constructors and Destructors Destructors must be defined virtual. Why? Consider base class A and a derived class B A* APtr ; //only the base class destructor APtr = new B; //is called with respect to the …… //object before the entire memory delete APtr; //occupied by the object is

returned. This leads to memory leak apart from other problems, since destructor of B not called.

If destructor of class A is virtual, then first the destructor of class B will be called , then the destructor of class A will be called. Finally, the entire memory block occupied by the object will be returned to OS

Page 32: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

If we expect the use of the delete operator on objects of a derived class in the presence of pointers of the base class, we must declare the destructor of the base class as virtual.

When a pointer of the base class points at a dynamically created object of the derived class and then deletes the memory occupied by the object, the entire block of memory is deleted. This is irrespective of whether the base class destructor is virtual or not.

Page 33: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

Virtual constructors Declaring a constructor virtual results in

compile-time error. Why ? If the constructor of class A is virtual, then in

A* p = new B ; the constructor of class B alone will be called and that of class A will not be called. A rough pointer will result.

The need to construct virtually arises very frequently while programming in C++

void abc (A * p ) { // defn of abc() function } Here an exact copy of the object at which ‘p’

points is required within the abc() function Calling a copy constructor seems to serve the

purpose i.e. A * q = new A (* p) or A A1(*p)

Page 34: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

This will work if a correct copy constructor is defined and if ‘p’ points to an object of base class and not to the derived class object

If ‘p’ points to the derived class object, then the object created will not be of the same type and will be smaller in size with less data members since it creates the object of class A

A clone function is to be defined to solve this class A{ public : virtual A * clone(){ return new A(* this);} //defn of class A };class B : public A { public : virtual B * clone(){ return new B(* this);} //defn of class B };

Page 35: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

Whenever a clone object is required, then the clone function is called and object created is subsequently destroyed

void abc( A * p) { …. ; A * q = p -> clone(); …. ; delete q; } Since clone function is virtual, its correct

version is called. Since the clone function constructs an object

and is virtual, it is called a virtual constructor There is actually nothing like virtual constructor

Page 36: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

# include<iostream.h>class convert { protected : double val1; double val2; public : convert (double i) { val1 = i ; } double get conv() { return val2; } double getinit () { return val1 ; } virtual void compute = 0 ; };class l_to_g : public convert { public : l_to_g (double i) : convert (i) { } void compute() { val2=val1/

3.7854;} };class f_to_c : public convert { public : f_to_c (double i) : convert (i) { } void compute() { val2=(val1-32)/

3.7854;} };

Page 37: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

int main(){ convert * p; l_to_g lgob(4); f_to_c fcob(70); p= &lgob; cout<< p->getinit()<<“litres is :” ; p-> compute(); cout << p->getconv() << “gallons\n” ;} p= &fcob; cout<< p->getinit()<<“in fahrenheit is :” ; p-> compute(); cout << p->getconv() << “celcius\n” ; return 0; }

Page 38: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM

//feet to metres class f_to_m : public convert { public : f_to_m (double i) : convert (i) { } void compute() { val2=val1/ 3.28;} }; p= &fmob; // in main() cout<< p->getinit()<<“feet is :” ; p-> compute(); cout << p->getconv() << “metres\n” ;} The class convert is an example of an abstract

class. Virtual function compute is not defined with oin compute because no meaningful definition can be provided. The class convert simply does not contain sufficient information for compute to be defined. It is only when convert is inherited by a derived class that is a complete type is created.

Page 39: VIRTUAL FUNCTIONS  AND  DYNAMIC POLYMORPHISM