Thursday, December 10, 2009

Virtual Functions in C++

The word Virtual refers to something that exists in effect but not in reality. A virtual function is a function that does not really exist but does affect some parts of the program. Let us see why we would need to use the virtual functions.

Consider a program to draw different shapes like triangles, circles, squares, ellipses etc. Consider that each of these classes has a member function called “draw()” by which the object is drawn. To be able to put all these objects together in one picture we would have to find a convenient way to call each object's draw() method. Let us look at the class declarations for a class "Shapes"
and derived classes "Circle" and "Square".

class Shapes{
....
....
public:
void draw(){
cout<<"Draw Base"< }

};
class Circle : public Shapes{
private:

int radius;

public:

Circle(int r);
void draw(){
cout<<"Draw Circle"< }
};
class Square:public Shapes{
private:
int length;

public:
Square(int l);
void draw(){
cout<<"Draw Square"< }
};
void main(){
Circle c;
Square s;
Shapes *ptr;

ptr=&c;
ptr->draw();
ptr=&s;
ptr->draw();
}

When pointers are used to access classes the arrow operator(->) can be used to access members of the class. We have assigned the address of the derived class to a pointer of the base class as seen in the statement:
ptr=&c; //where 'c' is an object of class Circle

Now, when we call the draw() method using:
ptr->draw();
we expect the "draw()" method of derived class would be called. However, the result of the program would be as follows:

Draw Base

Draw Base

Instead, we want to be able to use the function call to draw a square or any other object depending on which object "ptr" pointed to. This means, different draw() methods should be executed by the same function call.

For us to achieve this all the different classes of shapes must be derived from a single base class "Shapes". The "draw()" function must be declared to be "virtual" in the base class. The "draw()" function can then be redefined in each derived class. The "draw()" function in the base class declaration would be changed as follows:

class Shapes{
....
....

public:
virtual void draw(){
cout<<"Draw Base"< }

};

The keyword "virtual" indicates that the function draw() can have different versions for the derived classes. A virtual function allows derived classes to replace the implementation provided by the base class. The compiler makes sure the replacement is always called whenever the object in question is actually of the derived class.

The virtual function should be declared in the base class and can not be redeclared in a derived class. The return type of a member function must follow the keyword "virtual". If a hierarchy of derived classes is used, the virtual function has to be declared in the top-most level. Here, in the above example top most class is "Shapes" and the virtual can be declared in that.

A virtual function must be defined for the class in which it was first declared. Then even if no class is derived from that class, the virtual function can be used by the class. the derived class that does not need a special version of a virtual function need not provide one.

To redefine a virtual function in the derived class you need to provide a function exactly matching the virtual function. It must have the same arguments(in terms of number of parameters and data type), otherwise the compiler thinks you want to overload the virtual function. The return type does not have to match. For example if the virtual function of the class returns a pointer of its class, then you can redefine the function in a derived class and have it return pointer to the derived class, instead of a pointer of the base class. This is possible only with virtual member functions.



No comments:

Post a Comment