This example begins with the Actor 5 example from Chapter 13 (Polymorphism). We have two main tasks (one of which is broken into three smaller sub-tasks) to complete in this example:
The compiler can't process templates until concrete values replace the template variables. Generally, programmers specify a "real" data type to replace the template variables. For this reason, all template code is placed in a header file that is then included in and compiled with the client code. Begin by opening both CList files (CList.h and CList.cpp).
Select all of the code in CList.cpp and copy it to the clipboard. Next, go to CList.h and place the cursor after the class. If the code ends with an #endif
directive, the cursor must be before the directive (that is, between the class and the directive). Copy all of the code from CList.cpp into CList.h at the cursor location. Complete the merge step by editing the #include directives:
#include "Person.h"
from the original CList.h code#include "CList.h"
from the code that was copied from CList.cppOnce the merge operation is complete, we are ready to add the template syntax. We must add the template syntax at many different locations, but it is the same syntax, so we copy and paste it throughout the program.
template <class T>
above the CList class and above every function in the code copied into the CList header file<T>
between the class name and the ::
in each function header
There is still one important sub-step remaining in the "templatizing" process. As it stands, CList still specifies "Person" as the stored data type. This must be generalized by replacing Person
throughout the program with the template variable T
. Most editing programs, word processors, and program text editors alike support an operation called either "Search and Replace" or "Find and Replace." In visual studio, the operation is located in the Edit
menu:
(a) | (b) |
Edit
menu, select Find and Replace
and then Quick Replace
Generalizing the name of the stored data type (step 1.c) is the last step needed to "templatize" the CList class. Save the modified CList.h file and copy Actor5.cpp to Actor6.cpp.
Modifying the client (Actor5.cpp) to use the "templatized" class requires one simple modification: specifying the actual data type to store in the list. That means specifying the class name that will replace T
in the template code.
CList people; |
CList<Person> people; |
(a) | (b) |
The name of the template class and the name of the stored data type are ultimately joined together to form a new, user-created data type (known as an abstract data type or ADT). So, the compiler creates and includes a new class for each data type stored in the template class. For example, assume that we have a template named "Foo" that can hold or store fundamental data types (like int and double) and instances of classes (like Person):
Foo <int> list1; Foo <int> list2; Foo <double> list3; Foo <Person> list4;
The four variable definitions create three distinct versions of the Foo template class: one that holds ints, one that holds doubles, and one that holds instances of Person. In the first two definitions int
replaces the T
in the template; in the third definition double
replaces the T
; and in the last definition Person
replaces T
. So, only one version of the Foo code, with T
replaced by int
, is needed because both list1 and list2 are instantiated from the Foo<int> template.
Think of a container as a kind of software basket. It's common for programs to perform some iterative (looping) operation that creates new objects and puts them in the container. But the program only needs one container to hold many objects. Programmers must create the container where the program won't discard and replace it during each iteration.
while (...) { CList<Person> people; // error . . . } |
CList<Person> people; while (...) { . . . } |
(a) | (b) |