An object of a publicly derived class, as the Contractor class is, can also be treated as an object of its base class.
So, we can have an array of Employee objects which contains Contractor, PermanentEmployee and CasualEmployee objects.
Or an array of Animal objects which contains Cat, Dog, Pig, Wolf and Elephant objects.
Here goes an example of storing objects of different types in an array.
int main()
{
Contractor cn1( "Bob", "Smith", 40.0, 10.00 );
Employee emp1( "Fred", "Jones");
Employee* EmployeePtr[2];
EmployeePtr[0] = &cn1; // Points to a Contractor
EmployeePtr[1] = &emp1; // Points to an Employee
for(int i=0; i<2; i++)
EmployeePtr[i]->print();
return 0;
}
The output is disappointing
$ ./a.out
Employee::print() is executing
Bob SmithEmployee::print() is executing
Fred Jones
... to get the desired behaviour of treating Fred as a generic Employee and Bob as a Contractor without having to have a parallel container to record which is which and therefore safe to cast? We make print() a virtual function!
virtual void print() const;
Contractor::print() is executing
Employee::print() is executing
Bob Smith is a contractor with pay of $400.00
Employee::print() is executing
Fred Jones
C++ supports dynamic, or run-time, binding of functions through Vtables: Virtual Function Tables. When an object calls a function the call goes through it’s vtable and that directs the function call to the relevant version. This adds some overhead to our program. Any non-static function, other than a constructor, can be virtual.