Activity 16-3 - Polymorphism



Polymorphism refers to the ability to associate multiple meanings to one function name.  In order to give multiple meanings to a function name we use a special mechanism known as late binding.  Polymorphism is one of the key components of object oriented programming (OOP).

Late Binding
A virtual function is one that, in some sense, may be used before it is defined.  For example, you may remember that when we talked about function overloading we designed a function called area which was used to compute the area of different shapes.  In that lab, we separated the function for each shape using overloading which based its distinction on the type and number of arguments in the overloaded function.  We could use a similar approach with classes. In the case that we would use a class, each class needs a different function for computing the area of different shapes.  All these functions can be called area and we would create different objects for different shapes to make the separation. For example, we could have used object r for rectangle, c for a circle, and so forth.  Then each one of the functions could be executed, i.e., r.area( ) or c.area( ).  This is not something new, but now we wish to discuss this from a new viewpoint, virtual functions, defined in the parent of class area.

When we use a virtual function we tell the compiler that "we don't know how the function is implemented, wait until it is used in a program, and then get the implementation from the object instance."  The technique of waiting until run-time to determine the implementation of a procedure is called late binding or dynamic binding.

Virtual Functions in C++
Sometimes you are designing a program that needs to be versatile and handle various situations.  You may not be able to account for all possible situations.  For example, you have a program that is supposed to track sales, but you cannot anticipate all types of sales; regular sales, sales with discounts, mail orders, sales with shipping charges, etc. In a simple sale the bill is very simple while in more complicated ones, you may have several different things appearing on the bill.  You may also want to do some other things with the sales that were made, such as finding the largest or the smallest sale.

In order to do this, one approach would be to have a parent class Sale and make other types of sales derived classes (children) of that class.  The class Sale itself is a class that handles simple sales, sales with no discount and added charges.  Here is one way we may define class Sale with its implementation.

//This is the HEADER FILE sale.h.
//This is the INTERFACE for the class Sale.
//Sale is a class for simple sales.
#ifndef SALE_H
#define SALE_H

#include <iostream>
using namespace std;

namespace savitchsale
{

    class Sale
    {
    public:
        Sale();
        Sale(double the_price);
        virtual double bill() const;
        double savings(const Sale& other) const;
        //Returns the savings if you buy other instead of the calling object.
    protected:
        double price;
    };

    bool operator < (const Sale& first, const Sale& second);
    //Compares two sales to see which is larger.

}//savitchsale

#endif // SALE_H
// ****************************************************

The implementation looks like this:
//This is the IMPLEMENTATION FILE: sale.cpp
//This is the IMPLEMENTATION for the class Sale.
//The interface for the class Sale is in
//the header file sale.h.
#include "sale.h"

namespace savitchsale
{

    Sale::Sale() : price(0)
    {}

    Sale::Sale(double the_price) : price(the_price)
    {}

    double Sale::bill() const
    {
        return price;
    }

    double Sale::savings(const Sale& other) const
    {
        return ( bill() - other.bill() );
    }

    bool operator < (const Sale& first, const Sale& second)
    {
        return (first.bill() < second.bill());
    }

}//savitchsale

There are a few things that we need to discuss in this program.  Notice the reserved word virtual used with function bill in the class definition.  As you look carefully, you will find that function bill is used by function saving and operator <.  Since bill is declared as a virtual function, we later define derived classes of the class Sale and define their versions of the function bill, saving, and the overloaded operator <, to correspond to the objects of the derived classes.  Following is an example in which the derived class DiscountSale requires a different definition for its version of the function bill.

//This is the INTERFACE for the class DiscountSale.
#ifndef DISCOUNTSALE_H
#define DISCOUNTSALE_H
#include "sale.h"

namespace savitchsale
{
    class DiscountSale : public Sale
    {
    public:
        DiscountSale();
        DiscountSale(double the_price, double the_discount);
        //Discount is expressed as a percent of the price.
        double bill() const;
    protected:
        double discount;
    };
}//savitchsale
#endif //DISCOUNTSALE_H

The implementation for this class is shown below.

//This is the IMPLEMENTATION for the class DiscountSale.
#include "discountsale.h"

namespace savitchsale
{
    DiscountSale::DiscountSale() : Sale(), discount(0)
    {}

    DiscountSale::DiscountSale(double the_price, double the_discount)
              : Sale(the_price), discount(the_discount)
    {}

    double DiscountSale::bill() const
    {
        double fraction = discount/100;
        return (1 - fraction)*price;
    }
}//savitchsale

You may have noticed a new version of the bill function in the implementation of this derived class.  You may also have noticed that the member function saving and the overloaded operator < used with an object of the class DiscountSale both use the new version of bill.

The main program is shown below.

//Demonstrates the performance of the virtual function bill.
#include <iostream>
#include "sale.h" //Not really needed, but safe due to ifndef.
#include "discountsale.h"
using namespace std;
using namespace savitchsale;

int main()
{
    Sale simple(10.00);//One item at $10.00.
    DiscountSale discount(11.00, 10);//One item at $11.00 with a 10% discount.

    cout.setf(ios::fixed);
    cout.setf(ios::showpoint);
    cout.precision(2);

    if (discount < simple)
    {
        cout << "Discounted item is cheaper.\n";
        cout << "Savings is $" << simple.savings(discount) << endl;
    }
    else
        cout << "Discounted item is not cheaper.\n";

    return 0;
}

Exercise 16.3
Modify the the definition of the class Sale by deleting the reserved word virtual.  Before you run the program try to determine the output. Then compile the pieces and run the program.  Did you have the right answer?