C-Scene Issue #08
Another look at polymorphism
Tero Pulkkinen

Another look at polymorphism
----------------------------

 Introduction

Here I'll present something that most c++ programmers never learn. Most c++ books will teach it. However, it is simple enough for people who do not know object-oriented programming to use for learning the basics of object oriented programming. It is my opinion that the way the c++ books teaches dynamic dispatch and polymorphism is much too complicated , and this simple technique that I learned 6 years after I thought I knew what C++ was!

 

Creating an Interface

Every description of object orientation should start from description of an interface. In C++ you can create an interface like this::

class Printable
{
    public:
        virtual void print() = 0;
};
 

This defines an interface, which has exactly one method; print(). The declaration of a virtual function with "=0" flag in it tells us that the method is not implemented here, but that the implementation is deferred to later time.  After we have this, we can call print() method and expect it to work as specified in the interface. Here we expect print() method to output some text. The virtual keyword in the declaration says that polymorphism and dynamic dispatch is used by the print method. We'll come back to this later.

 

Calling the method from another class looks like this:

class Caller : private virtual Printable 
{
    public:
        void print_it() { print(); }
};
 

Here we have one method, print_it(), which has been implemented and it calls another method print(). We note that the part "private virtual Printable" says two things:

  1. private keyword tells us that Caller class *uses* Printable.
  2. virtual keyword tells us that Printable is an interface, and polymorphism is used. (again, virtual keyword is used in same purpose than before)

We'll come to this point again later.

One important thing to notice is that Caller class does not have implementation of print() method. We'll now provide another class that gives us one implementation of print() method:

class PrintText1 : public virtual Printable
{
    public:
        virtual void print() { cout << "Text1" << endl; }
};
 

Here we implement print() method and make it output some text. Important part here is again that "public virtual Printable". It says again two things:

  1. public says that PrintText1 class implements methods in Printable interface.
  2. virtual says that Printable is an interface and that we use polymorphism for it.

Now, we can make another implementation of Printable interface:

class PrintText2 : public virtual Printable
{
    public:
        virtual void print() { cout << "Text2" << endl; }
};
 

This is equivalent to the previous version, except that it implements the Printable interface differently, and outputs different text. The class name was changed to distinguish it from the previous implementation.  The important thing to notice is that both PrintText1 and PrintText2 are completely independent of Caller class. The only thing they share is the Printable interface.

Now we can return to the dynamic dispatch and polymorphism implied by the virtual keywords above. The most important thing to remember about Object-Oriented programming is that you can use the same operation for two or more different objects and it'll determined in runtime, which implementation to use. This makes users of some code independent of changes in the implementation. If you look at the Caller class, you'll notice we have that kind of method in print_it(). You can use it without worrying how the printing is really implemented.

You can make algorithms that uses Caller class:

void print_caller(Caller &obj)
{
    obj.print_it();
}
 

This code will be (in addition to Caller class) the reusable part of your application. Reuse is one of the advantages of OOP.

To finish our example, we need to create an object and ask our nice algorithm to print some text:

int main()
{
    class Text : public Caller, public PrintText1 { };
    Text text;
    print_caller(text);
}
 

This Text class binds print_it() function to print() function implemented in the PrintText1 class. The print_it() calls PrintText1's print() method. The importance of this technique is that Caller class does not depend on the implementation of PrintText1 class, and we can change it without changing Caller class! Because the Caller class was not modified, anything that uses Caller objects does not need to be changed when different PrintText1, PrintText2, PrintText3, ... classes are added to the system! The magic Text class that does this is called : Late Binding , or dynamic binding. This ability to defer choice of which implementation to apply to the latest possible situation is at the very heart of Object-Oriented Programming.

 

Why is this approach important ?

For experienced C++ programmers, the above way to implement polymorphism might seem odd., since most C++ book emphasizes the use uo pointers in polymorphism. The consequence of this approach is that the programmer ends up confronted with memory management problem, uninitialized variables, and many other annoying troubles that are the result of an inappropriate programming style that is often forced on new programmers who are seeking to learn Object Oriented Programming. 

You probably noticed that the above examples do not use pointers, nor do they allocate any dynamic memory. Also, they do not forget to initialize pointers. However, it does not have any advanced C++ features like constructors. There are no memory leaks inherent to the code, and it does not forget to implement the print() function. This approach to C++ is simple, and helps minimize the chances for serious mistakes.

The popular C++ programming books tend to overlook style and are often focused on warning the reader against using virtual inheritance, private inheritance. and multiple inheritance. The techniques shown here uses them all asafely, and iin a manner that is simple, useful , and a lot easier than the examples of polymorphism that are often found in in many programming textbooks.

 


This page is Copyright © 1999 By C Scene. All Rights Reserved