32
Virtual Function s tMyn 1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual in a base class will also be a virtual function in all classes derived (either directly or indirectly) from the base. To obtain polymorphic behaviour, each derived class may implement its own version of the virtual function.

Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Embed Size (px)

Citation preview

Page 1: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 1

Virtual Functions

• A virtual function is declared in a base class by using the keyword virtual.

• A function that you declare as virtual in a base class will also be a virtual function in all classes derived (either directly or indirectly) from the base.

• To obtain polymorphic behaviour, each derived class may implement its own version of the virtual function.

Page 2: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 2

class Box{public:virtual double volume() const;…};

class otherBox: public Box{public:virtual double volume() const;…};

class ToughPack: public Box{public:virtual double volume() const;…};

class Carton: public Box{public:virtual double volume() const;…};

pbox is type pointer to Box. The version of volume() function called is dependent on the type of object pointed to by pbox.

double result=pbox->volume();

Diagram 1. Illustration of how a call to a virtual function through a pointer is resolved dynamically.

Page 3: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 3

• Virtual function calls can be made using a variable that is a pointer or a reference to a base class object.

• In the diagram 1 the pointer to base is used to store the address of an object with a type corresponding to one of the derived classes.

• It could point to an object of any of the three derived classes shown, or of course to a base class object.

• Which volume() function is called will depend on the type of the object to which the pointer points when the call is executed.

• Describing a class as polymorphic means that it’s a class that contains at least one virtual function.

Page 4: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 4

• Note that a call to a virtual function using an object will always be resolved statically.

• You only get dynamic resolution of calls to virtual functions through a pointer or a reference.

• Let’s make a very small change to the Box class: we just need to add the keyword virtual to the declaration of the calcVol() function (and for the sake of symmetry, same keyword to the derived class):

Page 5: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 5

#include "stdafx.h"#include <iostream>#include <string>using namespace System;using namespace std;class Box{public:

Box(); Box(double, double, double); ~Box(); void displayVol(); virtual double calcVol() const;protected: double length;

double breadth; double height;

};

We can declare the functions as const because they do not alter any data members of the class.

The keyword virtual in the base classdefinition of the function volume() issufficient to determine that all declarations of the function in derivedclasses will also be understood to bevirtual.

Page 6: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 6

Box::Box(){

cout<<"Base class default constr., object "<<this<<endl;cout<<"Length: ";cin>>length; cin.get();cout<<"Breadth: ";

cin>>breadth; cin.get();cout<<"Height: ";

cin>>height; cin.get();}Box::Box(double lv, double bv, double hv){

cout<<"Base class constructor with 3 params., object ” <<this<<endl;

length=lv; breadth=bv; height=hv;

}

Page 7: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 7

Box::~Box(){ cout<<"Base class destructor, object "<<this<<endl;}void Box::displayVol(){ cout<<"Usable volume is "<<calcVol()<<endl;}double Box::calcVol() const{ return length*breadth*height;}

Do not add the virtual keyword to the function definition!

Page 8: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 8

class Carton:public Box{public:

Carton(); Carton(string); Carton(double, double, double, string); ~Carton(); virtual double calcVol() const;private: string* text;};Carton::Carton():Box(){ cout<<"Derived class default constr., object "<<this<<endl;

text=new string;cout<<"Typical usage: ";

getline(cin, *text);}

Page 9: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 9

Carton::Carton(string message):Box(){

cout<<"Derived class constructor with 2 params, object " <<this<<endl;

text=new string; *text=message;

}Carton::Carton(double lVal, double bVal, double hVal, string message):Box(lVal, bVal, hVal){

cout<<"Derived class constructor with 4 params., object ” <<this<<endl;

text=new string; *text=message;

}

Page 10: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 10

Carton::~Carton(){

cout<<"Derived class destructor, object "<<this<<endl; delete text; text=0;}double Carton::calcVol() const{ return 0.85*length*breadth*height;}

Page 11: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 11

int main(array<System::String ^> ^args){

Box first=Box(); Carton second=Carton(); Box* pBox=&first;

pBox->displayVol();pBox=&second;pBox->displayVol();

return 0;}

Page 12: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 12

Page 13: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 13

• It is recommended that you do use the keyword virtual with all declarations of virtual functions in derived classes, since it makes it clear to anyone reading the derived class definition that the functions are indeed virtual, and that they will be linked to dynamically.

• Let’s make two more tests:

Page 14: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 14

int main(array<System::String ^> ^args){

Box first=Box(); Carton second=Carton(); first.displayVol();

second.displayVol(); return 0;}

This simply calls the baseclass version of calcVol(),since first is of type Box.

Page 15: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 15

Page 16: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 16

• So the statement second.displayVol() calls the displayVol() function defined in the Box class – there aren’t any other versions of displayVol()!

However, the call to calcVol() in displayVol() is resolved to the version defined in the derived class, because object second is of type Carton.

Page 17: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 17

• For a function to behave virtually you must declare and define it with the same name and parameter list in any derived class as it has in the base class.

• Further, if you have declared the base class function as const, then you must declare the derived class function to be const as well.

Page 18: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 18

• To ensure that the correct destructor is called for objects allocated in the free store, we need to employ virtual class destructors.

• To implement a virtual class destructor, we just add the keyword virtual to the destructor declaration in the class.

• This signals to the compiler that destructor calls through a pointer or a reference parameter should have dynamic binding, and so the destructor will be selected at runtime.

Page 19: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 19

• This works in spite of the fact that all the destructors have different names; destructors are treated as a special case for this purpose.

• Recall the example:

Page 20: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 20

…int main(array<System::String ^> ^args){

Box* first=new Carton();delete first;

return 0;}

Page 21: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 21

Unfortunately the derived class destructorwill never be called!

Page 22: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 22

• Let’s add the keyword virtual to the base class destructor declaration:

Page 23: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 23

…class Box{public:

Box(); Box(double, double, double); virtual ~Box(); void displayVol(); virtual double calcVol() const;protected: double length;

double breadth; double height;

};…

This is the only difference compared to the previous one!!

Page 24: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 24

…class Carton:public Box{public:

Carton(); Carton(string); Carton(double, double, double, string); virtual ~Carton(); virtual double calcVol() const;private: string* text;};…

But we are free to have symmetry…

Page 25: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 25

int main(array<System::String ^> ^args){

Box* first=new Carton();delete first;

return 0;}

Page 26: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 26

Page 27: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 27

• Why would anyone use a reference or pointer of base class type to access an object of a subclass?

• Suppose we need to construct a function that will work with all subclasses of a base class.

• With polymorphism, the function could be coded to expect a pointer or reference to the base class type and behave correctly and distinctly when different subclasses are passed in.

• As a second example, suppose we wish to make a list or array containing references or pointers to objects of different subtypes of a single base class.

Page 28: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 28

• If the type of the array is selected to be either reference or pointer of the base class, subclasses of multiple types can be stored.

• And more importantly, the pointers or references will behave correctly and distinctly according to what subclass they access.

• This is polymorphism. So, in C++, the first requirement for polymorphism is that the objects must be accessed via pointer or reference.

Page 29: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 29

• A second requirement for polymorphism to work is that the functions whose polymorphic behaviour is desired must be declared as virtual.

• Overridden functions not declared as virtual (=redefinition) will behave correctly only for statically bound objects; those known at compile time.

• For base class pointers or references bound to objects during execution, polymorphism will not be seen if a function is not declared virtual.

Page 30: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 30

Overriding

• When a virtual function definition is changed in a derived class, then the function definition is said to be overridden.

• A distinction is sometimes made between the terms redefined and overridden.

• Both terms refer to changing the definition of the function in a derived class.

• If the function is a virtual function, it is called overriding.

• If the function is not a virtual function, it is called redefining.

Page 31: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 31

• If a class declares any virtual functions, the destructor of the class should be declared as virtual as well.

• This ensures that regardless of the actual subclass of an object accessed via a base class pointer or reference, the correct destructor will clean it up.

Page 32: Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual

Virtual Functions tMyn 32

• Why not declare all functions as virtual? • This could be done, but involves additional overhead.• The compiler creates a virtual function table that is

used in the polymorphism mechanism. Avoiding unnecessary details, the more functions that are declared as virtual, the greater the overhead to create and maintain these tables. But, by declaring all functions virtual, redesign may be avoided if the classes need to change.

• Some C++ programmers declare all functions virtual if any need be. Some don't. In some programming languages, such as Java, all functions are virtual by default.