Virtual functions let you have an 'interface' while leaving the actual 'implementation' details (ie: how it's actually done) to the child class.
This is useful when you have many classes which can be abstracted to a common interface.
An academic example is a 'Shape' class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
|
class Shape
{
public:
virtual int area() = 0; // a pure virtual 'area' function
};
/*
Shape's area function can't possibly calculate the area of the shape because
there's no way to know what kind of shape it is... and each shape's area is computed
differently
*/
class Rectangle : public Shape
{
int width;
int height;
public:
virtual int area() override
{
return width * height; // <- rectangle area computation
}
};
class Circle : public Shape
{
int radius;
public:
virtual int area() override
{
return 2 * pi * radius; // <- circle area computation
}
};
|
This allows you to use and manipulate a 'Shape' reference or pointer without knowing exactly what kind of shape you're dealing with. This allows you to write generic/unassuming code that is easily reusable.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
void printArea( Shape& shape )
{
cout << "The area of this shape is: " << shape.area();
// we call 'area' here... but we don't know what kind of Shape it is! So how can it
// know which formula to use?
//
// That's what being 'virtual' means. It will figure out what kind of Shape it is, and
// call the appropriate function automatically.
}
// Effectively this means the 'printArea' function works with ANY shape... not just circles,
// not just rectangles... but any and all classes derived from Shape. Even classes that
// you have not written yet that you might add in the future!!!
int main()
{
Rectangle r;
Circle c;
// ...
printArea( r ); // since Rectangle is derived from Shape, we can pass 'r' to this function
printArea( c ); // same for c, since Circle is derived from Shape
}
|
Another example would be something like a File class. You can read/write data to a file... but there might be different kinds of files:
- Files that write to disk
- Files that are zipped or otherwise compressed
- Files that are uploaded/downloaded from the internet
- etc
A common 'File' abstract base class would let you use all these different file types with the same code. And having a virtual read/write function would allow the derived types to do the reading/writing in their own specific way.