How Do They Compare?
My primary motivation for exploring alternative versions of polymorphic insertion functions was to create a version that uses less memory than the virtual method version while obtaining comparable performance.
To compare the three versions of code, I experimented with six test cases; see Table 1. The first two test cases use objects and not pointers, so they are nonpolymorphic.
<b>Test 1</b> Employee employee1; cout << employee1; <b>Test 2</b> Manager m1; cout << manager1; <b>Test 3</b> Employee* pEmp = new Employee; cout << *pEmp; <b>Test 4</b> Manager* pManager1 = new Manager; cout << *pManager1; <b>Test 5</b> Employee* pEmp = new Manager; cout << *pEmp; <b>Test 6</b> Employee* pEmp = new Salesperson; cout << *pEmp;
The first test calls the Employee's insertion function using an Employee object. Likewise, the second test calls the Manager's function using a Manager object. The next two test cases use pointers where the type of the pointer matches the type of the object that is being pointed to by the pointer. The third uses an Employee pointer that is pointing to an Employee object. The fourth test uses a Manager pointer that is pointing to a Manager object. The last two test cases assess the polymorphic behavior of the functions. They both use an Employee pointer that points to a Manager and Salesperson object, respectively.
Figure 2 shows the test timing data for each version. The time unit is microseconds. These numbers are the average of several runs using Visual C++ Version 7.
I expected version 2 to be slower because it uses runtime type information (RTTI), but was surprised that it was so much slower. Keep in mind, version 2 is using just as much memory as version 1.
As I hoped, versions 1 and 3 are comparable in performance. In fact, version 3 is a little faster for the first and third test cases. Both of these test cases deal with parent objects. However, version 3 is a little slower for the test cases dealing with child objects.
Version 1 requires a class to have a vtable, plus every object must contain a pointer to the vtable. Version 3 requires each object to have a type identifier, but this needs less memory than the pointer for a vtable. So, version 3 uses less memory per object and per class.
Conclusion
In this article I presented three different techniques for polymorphic insertion functions. The third version is a viable option for situations with a small class hierarchy where more parent objects are used than children. In these examples, I assumed that there would be many more Employee objects than Manager and Salesperson objects.