Since there's no virtual int area();
declared in CPolygon
, there's no linkage for that method to objects of class CPolygon
in general.
Basically, you're expecting method lookup to happen at run time (like it's done in Python, JavaScript, and other languages), but in C++ it happens at compile time. The above code implicitly says to the C++ compiler, "CRectangle
and CTriangle
have methods named area
but they have nothing to do with each other nor do they have anything to do with CPolygon
."
Remember that the C++ compiler often does not see all the subclasses of a given class at compile time.
why would I use a pointer of base class to point to members of derived class (by implementing virtual functions) when I can just create an object of derived class and call the area function of it and get my work done?
Because it's rare that code knows every last little detail about the objects it works with, and often is has no need to know, so there's simplification to be had.
For example, in this case, if the entirety of your code was one function that created a CTriangle
and then called its area
method to get the area, print it, and terminate, then yeah, there's not much point. The code is nothing more than a glorified calculator with extra verbage.
But in the real world, you don't have the luxury of everything fitting in one function, or source file. So a piece of code might know that it has a pointer to CPolygon
but not what specific subclass. And yet that code needs to know its area. For example, a function that calculates an extruded volume given a cross section polygon and a thickness:
int extruded_volume(CPolygon* poly, int thickness)
{
return thickness * poly->area();
}
Imagine this function is declared in Extrusion.h
and defined in Extrusion.cpp
. Further, imagine that each of CPolygon
, CRectangle
, and CTriangle
are separately declared in .h
files and defined in .cpp
files named after the classes respectively. Then Extrusion.h
only needs #include "CPolygon.h"
and can go its life without knowing anything about the various subclasses. This works if and only if area
is a virtual method.
This also allows subclasses of CPolygon
to be added later. For example, a subclass CEllipse
representing an ellipse whose "width" and "height" were its minor and major axes lengths, respectively:
class CEllipse: public CPolygon {
public:
int area ()
{ return M_PI * (width/2) * (height/2); }
};
Since we used a virtual method, a CEllipse*
could be passed to extruded_volume
without changing the latter's code at all.
If area
weren't a virtual method, then you would need a separate version of extruded_volume
for every possible polygon:
template<typename T>
int extruded_volume(T* poly, int thickness)
{
return thickness * poly->area();
}
In this case, the code bloat is minor because there's not much code there, but in a larger system this could well be unacceptable. Also note that everything that calls extruded_volume
will likely need to be a template as well.