📄 ch19.htm
字号:
Note that <TT>Animal</TT> has a default constructor. This is necessary because, when
you add an object to an array, the object's default constructor is used to create
the object. This creates some difficulties, as you'll see.</P>
<P>On line 79, the function <TT>IntFillFunction()</TT> is declared. The prototype
indicates that this function takes an integer array. Note that this is not a template
function. <TT>IntFillFunction()</TT> expects only one type of an array--an integer
array. Similarly, on line 80, <TT>AnimalFillFunction()</TT> is declared to take an
<TT>Array </TT>of <TT>Animal</TT>.</P>
<P>The implementations for these functions are different from one another, because
filling an array of integers does not have to be accomplished in the same way as
filling an array of <TT>Animal</TT>s.
<H4 ALIGN="CENTER"><A NAME="Heading24"></A><FONT COLOR="#000077">Specialized Functions</FONT></H4>
<P>If you uncomment the <TT>print</TT> statements in <TT>Animal</TT>'s constructors
and destructor in Listing 19.5, you'll find there are unanticipated extra constructions
and destructions of <TT>Animal</TT>s.</P>
<P>When an object is added to an array, the object's default constructor is called.
The <TT>Array</TT> constructor, however, goes on to assign <TT>0</TT> to the value
of each member of the array, as shown on lines 59 and 60 of Listing 19.2.</P>
<P>When you write <TT>someAnimal = (Animal) 0;</TT>, you call the default <TT>operator=</TT>
for <TT>Animal</TT>. This causes a temporary <TT>Animal</TT> object to be created,
using the constructor, which takes an integer (zero). That temporary is used as the
right-hand side of the <TT>operator=</TT> and then is destroyed.</P>
<P>This is an unfortunate waste of time, because the <TT>Animal</TT> object was already
properly initialized. However, you can't remove this line, because integers are not
automatically initialized to a value of <TT>0</TT>. The solution is to teach the
template not to use this constructor for <TT>Animal</TT>s, but to use a special <TT>Animal</TT>
constructor.</P>
<P>You can provide an explicit implementation for the <TT>Animal</TT> class, as indicated
in Listing 19.6.</P>
<P><A NAME="Heading25"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 19.6. Specializing
template implementations.</B></FONT>
<PRE><FONT COLOR="#0066FF">1: #include <iostream.h>
2:
3: const int DefaultSize = 3;
4:
5: // A trivial class for adding to arrays
6: class Animal
7: {
8: public:
9: // constructors
10: Animal(int);
11: Animal();
12: ~Animal();
13:
14: // accessors
15: int GetWeight() const { return itsWeight; }
16: void SetWeight(int theWeight) { itsWeight = theWeight; }
17:
18: // friend operators
19: friend ostream& operator<< (ostream&, const Animal&);
20:
21: private:
22: int itsWeight;
23: };
24:
25: // extraction operator for printing animals
26: ostream& operator<<
27: (ostream& theStream, const Animal& theAnimal)
28: {
29: theStream << theAnimal.GetWeight();
30: return theStream;
31: }
32:
33: Animal::Animal(int weight):
34: itsWeight(weight)
35: {
36: cout << "animal(int) ";
37: }
38:
39: Animal::Animal():
40: itsWeight(0)
41: {
42: cout << "animal() ";
43: }
44:
45: Animal::~Animal()
46: {
47: cout << "Destroyed an animal...";
48: }
49:
50: template <class T> // declare the template and the parameter
51: class Array // the class being parameterized
52: {
53: public:
54: Array(int itsSize = DefaultSize);
55: Array(const Array &rhs);
56: ~Array() { delete [] pType; }
57:
58: // operators
59: Array& operator=(const Array&);
60: T& operator[](int offSet) { return pType[offSet]; }
61: const T& operator[](int offSet) const
62: { return pType[offSet]; }
62:
63: // accessors
64: int GetSize() const { return itsSize; }
65:
66: // friend function
67: friend ostream& operator<< (ostream&, const Array<T>&);
68:
69: private:
70: T *pType;
71: int itsSize;
72: };
73:
74: template <class T>
75: Array<T>::Array(int size = DefaultSize):
76: itsSize(size)
77: {
78: pType = new T[size];
79: for (int i = 0; i<size; i++)
80: pType[i] = (T)0;
81: }
82:
83: template <class T>
84: Array<T>& Array<T>::operator=(const Array &rhs)
85: {
86: if (this == &rhs)
87: return *this;
88: delete [] pType;
89: itsSize = rhs.GetSize();
90: pType = new T[itsSize];
91: for (int i = 0; i<itsSize; i++)
92: pType[i] = rhs[i];
93: return *this;
94: }
95: template <class T>
96: Array<T>::Array(const Array &rhs)
97: {
98: itsSize = rhs.GetSize();
99: pType = new T[itsSize];
100: for (int i = 0; i<itsSize; i++)
101: pType[i] = rhs[i];
102: }
103:
104:
105: template <class T>
106: ostream& operator<< (ostream& output, const Array<T>& theArray)
107: {
108: for (int i = 0; i<theArray.GetSize(); i++)
109: output << "[" << i << "] " << theArray[i] << endl;
110: return output;
111: }
112:
113:
114: Array<Animal>::Array(int AnimalArraySize):
115: itsSize(AnimalArraySize)
116: {
117: pType = new Animal[AnimalArraySize];
118: }
119:
120:
121: void IntFillFunction(Array<int>& theArray);
122: void AnimalFillFunction(Array<Animal>& theArray);
123: enum BOOL {FALSE, TRUE};
124:
125: int main()
126: {
127: Array<int> intArray;
128: Array<Animal> animalArray;
129: IntFillFunction(intArray);
130: AnimalFillFunction(animalArray);
131: cout << "intArray...\n" << intArray;
132: cout << "\nanimalArray...\n" << animalArray << endl;
133: return 0;
134: }
135:
136: void IntFillFunction(Array<int>& theArray)
137: {
138: BOOL Stop = FALSE;
139: int offset, value;
140: while (!Stop)
141: {
142: cout << "Enter an offset (0-9) and a value. ";
143: cout << "(-1 to stop): " ;
143: cin >> offset >> value;
144: if (offset < 0)
145: break;
146: if (offset > 9)
147: {
148: cout << "***Please use values between 0 and 9.***\n";
149: continue;
150: }
151: theArray[offset] = value;
152: }
153: }
154:
155:
156: void AnimalFillFunction(Array<Animal>& theArray)
157: {
158: Animal * pAnimal;
159: for (int i = 0; i<theArray.GetSize(); i++)
160: {
161: pAnimal = new Animal(i*10);
162: theArray[i] = *pAnimal;
163: delete pAnimal;
164: }
<TT>165: }</TT></FONT></PRE>
<BLOCKQUOTE>
<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>Line numbers have been added to
the output to make analysis easier. Line numbers will not appear in your output.
<HR>
</BLOCKQUOTE>
<PRE><FONT COLOR="#0066FF">Output: 1: animal() animal() animal() Enter an offset (0-9) and a value. (-1 to stop): 0 0
2: Enter an offset (0-9) and a value. (-1 to stop): 1 1
3: Enter an offset (0-9) and a value. (-1 to stop): 2 2
4: Enter an offset (0-9) and a value. (-1 to stop): 3 3
5: Enter an offset (0-9) and a value. (-1 to stop): -1 -1
6: animal(int) Destroyed an animal...animal(int) Destroyed an animal...animal(int) Destroyed an animal...initArray...
7: [0] 0
8: [1] 1
9: [2] 2
10:
11: animal array...
12: [0] 0
13: [1] 10
14: [2] 20
15:
16: Destroyed an animal...Destroyed an animal...Destroyed an animal...
17:
<<< Second run >>>
18: animal(int) Destroyed an animal...
19: animal(int) Destroyed an animal...
20: animal(int) Destroyed an animal...
21: Enter an offset (0-9) and a value. (-1 to stop): 0 0
22: Enter an offset (0-9) and a value. (-1 to stop): 1 1
23: Enter an offset (0-9) and a value. (-1 to stop): 2 2
24: Enter an offset (0-9) and a value. (-1 to stop): 3 3
25: animal(int)
26: Destroyed an animal...
27: animal(int)
28: Destroyed an animal...
29: animal(int)
30: Destroyed an animal...
31: initArray...
32: [0] 0
33: [1] 1
34: [2] 2
35:
36: animal array...
37: [0] 0
38: [1] 10
39: [2] 20
40:
41: Destroyed an animal...
42: Destroyed an animal...
43: Destroyed an animal...
</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>Listing 19.6 reproduces both
classes in their entirety, so that you can see the creation and destruction of temporary
<TT>Animal</TT> objects. The value of <TT>DefaultSize</TT> has been reduced to <TT>3</TT>
to simplify the output.<BR>
The <TT>Animal</TT> constructors and destructors on lines 33-48 each print a statement
indicating when they are called.</P>
<P>On lines 74-81, the template behavior of an <TT>Array</TT> constructor is declared.
On lines 114-118, the specialized constructor for an <TT>Array</TT> of <TT>Animal</TT>s
is demonstrated. Note that in this special constructor, the default constructor is
allowed to set the initial value for each <TT>Animal</TT>, and no explicit assignment
is done.</P>
<P>The first time this program is run, the first set of output is shown. Line 1 of
the output shows the three default constructors called by creating the array. The
user enters four numbers, and these are entered into the integer array.</P>
<P>Execution jumps to <TT>AnimalFillFunction()</TT>. Here a temporary <TT>Animal</TT>
object is created on the heap on line 161, and its value is used to modify the <TT>Animal</TT>
object in the array on line 162. On line 163, the temporary <TT>Animal</TT> is destroyed.
This is repeated for each member of the array and is reflected in the output on line
6.</P>
<P>At the end of the program, the arrays are destroyed, and when their destructors
are called, all their objects are destroyed as well. This is reflected in the output
on line 16.</P>
<P>For the second set of output (lines 18-43), the special implementation of the
array of character constructor, shown on lines 114-118 of the program, is commented
out. When the program is run again, the <TT>template</TT> constructor, shown on lines
74-81 of the program, is run when the <TT>Animal</TT> array is constructed.</P>
<P>This causes temporary <TT>Animal</TT> objects to be called for each member of
the array on lines 79 and 80 of the program, and is reflected in the output on lines
18 to 20 of the output.</P>
<P>In all other respects, the output for the two runs is identical, as you would
expect.
<H4 ALIGN="CENTER"><A NAME="Heading27"></A><FONT COLOR="#000077">Static Members and
Templates</FONT></H4>
<P>A template can declare static data members. Each instantiation of the template
then has its own set of static data, one per class type. That is, if you add a static
member to the <TT>Array</TT> class (for example, a counter of how many arrays have
been created), you will have one such member per type: one for all the arrays of
<TT>Animal</TT>s, and another for all the arrays of integers. Listing 19.7 adds a
static member and a static function to the <TT>Array</TT> class.</P>
<P><A NAME="Heading28"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 19.7. Using
static member data and functions with templates.</B></FONT>
<PRE><FONT COLOR="#0066FF">1: #include <iostream.h>
2:
3: template <class T> // declare the template and the parameter
4: class Array // the class being parameterized
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -