C++ virtual functions
As mentioned earlier, 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 the polymorphism is therefore the ability to refer to the objects without any regard to their classes . This necessary the use of a single pointer variable to refer to the objects of different
classes.
Here we use the pointer to base(super) class to refer to all the derived objects. but we just discovered that a base pointer, even it is made to contain the address of a derived class, always
executes the function in the base class.The compiler simply ignores the content.
how do we then achieve polymorphism? it is achieved using virtual function
When we use the same function name in both the base and derived classes.The function in base class in declared as virtual using keyword virtual preceding its normal declaration
when a function is made virtual, C++ language 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. This by making the base
pointer to point to different objects, we can execute different version of virtual function
VIRTUAL FUNCTIONS
<iostream >
using namespace std;
class Base
{
:
display()
{
cout << "\n display base";
}
show()
{
cout << "\n show base";
}
};
class derived: Base
{
:
display()
{
cout << "\n Display Derived";
}
show()
{
cout << "\n show derived";
}
};
main()
{
Base B;
derived D;
Base *bptr;
cout << "\n bptr points to Base \n";
bptr=&B;
bptr->display();
bptr->show();
cout << "\n \n bptr points to derived \n";
bptr=&D;
bptr->display();
bptr->show();
}
|
output:
bptr points to Base
Display base
show base
bptr points to derived
Display base
show derived
|
when bptr is made to point to the object D, The statement
bptr->display();
calls only the function associated with the Base(Base::display()), whereas the statement
bptr->show();
calls thee derived version of show(). This is because the function display() has not been made virtual in the Base class one important point to remember is that, we must access virtual functions through the use of a pointer declared as pointer to the base class. here is question why cannot we use the object name (with the dot operator) the same way as any other member function to call the virtual function? we can but remember run time polymorphism is achieved only when a virtual function is accessed through a pointer to the base class.
Let us take an example where virtual function are implemented in practice. consider a books show which sells both books and video tapes. We can create a class known as media that stores the title and price of a publication. we can create a class known as media that stores the title and price of a publication
we can then create two derived class one for storing the number of pages in a book and another for storing the playing time of a type
let is see class hierarchy for the book shop
The class are implemented in program A display() function is used in all the classes to display the contents of class .
Notice: The function display() has been declared virtual in media, the base class. In main program we create a heterogeneous list of pointer of type media as shown example in below
media *list[2];=
{
&book1; [1], &tape1
};
|
The base pointers list[0] and list[1] are initialized with the addresses of objects books=1 and tape1
RUNTIME POLYMORPHISM
<iostream>
<cstring>
class media
{
:
title[50];
price;
:
media(char *s, float a)
{
strcpy(title,s);
price=a;
}
display()
{
// empty virtual function
}
};
class book: public media
{
pages;
:
book(char *s,float a, int p):media(s,a)
{
pages=p;
}
display();
};
class tape: public media
{
time;
:
tape(char *s,float a,float t):media(s,a)
{
time=t;
}
display();
};
book::display()
{
std::cout << "\n title:" << title;
std::cout << "\n pages:" << pages;
std::cout <<"\n price:" << price;
}
tape::display()
{
std::cout << "\n Title:" << title;
std::cout << "\n play time:" << time <<"mins";
std::cout << "\n price:" << price;
}
main()
{
*title=new char[30];
price,time;
pages;
// book details
std::cout << "\nEnter Books Details \n";
std::cout << "Title:";
std::cin >> title;
std::cout << "price:";
std::cin >> price;
std::cout << "pages:";
std::cin >> pages;
book book1(title,price,pages);
// Tape Details
std::cout << "\n Enter Tape Details\n";
std::cout << "Title:";
std::cin >> title;
std::cout << "price:";
std::cin >> price;
std::cout << "play time(mins):";
std::cin >> time;
tape tape1(title, price, time);
media* list[2];
list[0]=&book1;
list[1]=&tape1;
std::cout << "\n MEDIA DETAILS";
std::cout << "\n....... Book.........";
list[0]->display();
std::cout << "\n....TAPE......";
list[1]->display();
}
|
Enter Books Details
Title:E Balaguruswami
price:99
pages:350
Enter Tape Details
Title:programming concepts
price:95
play time(mins):60
MEDIA DETAILS
……. Book………
title:E Balaguruswami
pages:99
price:350
….TAPE……
Title:programming concepts
play time:95
price:95
|
Rules for virtual functions
when virtual function are created for implementing late binding, we should observe some basic rules that satisfy the compiler requirements
1. The virtual function must be member of some class
2. They cannot be static members.
3. They are accessed by using object pointers.
4. A virtual function can be a friend of another class.
5. A virtual function in a base class must be defined, even through it may not be used.
6. The prototype of the base class version of a virtual function and all the derived class.
versions must be identical. if two function with the same name have different prototypes, C++ consider them as overloaded functions, and the virtual function mechanism is ignored
7. we cannot have virtual constructors, but we can have virtual destructor.
8 while a base pointer can point to any type of the derived object, the reverse is not true. That is to say, we cannot use pointer to a
derived class to access an object of the base type.
9. When a base pointer points to a derived class, incrementing or decrementing it will not make it to point to the next object of the derived class. it is incremented or decremented only relative to its base type. Therefore we should not use this method to move the pointer to the next object.
10. if a virtual function is defined in the base class, it need not be necessarily redefined in the derived class. In such cases call will invoke the base function.