Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com
Answertopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions
Privacy Policy

  




 

 

Thinking in C++
Prev Contents / Index Next

Overview of templates

Now a problem arises. You have an IntStack, which holds integers. But you want a stack that holds shapes or aircraft or plants or something else. Reinventing your source code every time doesn’t seem like a very intelligent approach with a language that touts reusability. There must be a better way.

There are three techniques for source code reuse in this situation: the C way, presented here for contrast; the Smalltalk approach, which significantly affected C++; and the C++ approach: templates.

The C solution. Of course you’re trying to get away from the C approach because it’s messy and error prone and completely inelegant. In this approach, you copy the source code for a Stack and make modifications by hand, introducing new errors in the process. This is certainly not a very productive technique.

The Smalltalk solution. Smalltalk (and Java, following its example) took a simple and straightforward approach: You want to reuse code, so use inheritance. To implement this, each container class holds items of the generic base class Object (similar to the example at the end of Chapter 15). But because the library in Smalltalk is of such fundamental importance, you don’t ever create a class from scratch. Instead, you must always inherit it from an existing class. You find a class as close as possible to the one you want, inherit from it, and make a few changes. Obviously, this is a benefit because it minimizes your effort (and explains why you spend a lot of time learning the class library before becoming an effective Smalltalk programmer).

But it also means that all classes in Smalltalk end up being part of a single inheritance tree. You must inherit from a branch of this tree when creating a new class. Most of the tree is already there (it’s the Smalltalk class library), and at the root of the tree is a class called Object – the same class that each Smalltalk container holds.

This is a neat trick because it means that every class in the Smalltalk (and Java[59]) class hierarchy is derived from Object, so every class can be held in every container (including that container itself). This type of single-tree hierarchy based on a fundamental generic type (often named Object, which is also the case in Java) is referred to as an “object-based hierarchy.” You may have heard this term and assumed it was some new fundamental concept in OOP, like polymorphism. It simply refers to a class hierarchy with Object (or some similar name) at its root and container classes that hold Object.

Because the Smalltalk class library had a much longer history and experience behind it than did C++, and because the original C++ compilers had no container class libraries, it seemed like a good idea to duplicate the Smalltalk library in C++. This was done as an experiment with an early C++ implementation[60], and because it represented a significant body of code, many people began using it. In the process of trying to use the container classes, they discovered a problem.

The problem was that in Smalltalk (and most other OOP languages that I know of), all classes are automatically derived from a single hierarchy, but this isn’t true in C++. You might have your nice object-based hierarchy with its container classes, but then you might buy a set of shape classes or aircraft classes from another vendor who didn’t use that hierarchy. (For one thing, using that hierarchy imposes overhead, which C programmers eschew.) How do you insert a separate class tree into the container class in your object-based hierarchy? Here’s what the problem looks like:


Because C++ supports multiple independent hierarchies, Smalltalk’s object-based hierarchy does not work so well.

The solution seemed obvious. If you can have many inheritance hierarchies, then you should be able to inherit from more than one class: Multiple inheritance will solve the problem. So you do the following (a similar example was given at the end of Chapter 15):


Now OShape has Shape’s characteristics and behaviors, but because it is also derived from Object it can be placed in Container. The extra inheritance into OCircle, OSquare, etc. is necessary so that those classes can be upcast into OShape and thus retain the correct behavior. You can see that things are rapidly getting messy.

Compiler vendors invented and included their own object-based container-class hierarchies, most of which have since been replaced by template versions. You can argue that multiple inheritance is needed for solving general programming problems, but you’ll see in Volume 2 of this book that its complexity is best avoided except in special cases.

Thinking in C++
Prev Contents / Index Next

 
 
   Reproduced courtesy of Bruce Eckel, MindView, Inc. Design by Interspire