📄 ch19.htm
字号:
31: {
32: public:
33: // constructors
34: Array(int itsSize = DefaultSize);
35: Array(const Array &rhs);
36: ~Array() { delete [] pType; }
37:
38: // operators
39: Array& operator=(const Array&);
40: T& operator[](int offSet) { return pType[offSet]; }
41: const T& operator[](int offSet) const
42: { return pType[offSet]; }
43: // accessors
44: int GetSize() const { return itsSize; }
45:
46: private:
47: T *pType;
48: int itsSize;
49: };
50:
51: // implementations follow...
52:
53: // implement the Constructor
54: template <class T>
55: Array<T>::Array(int size = DefaultSize):
56: itsSize(size)
57: {
58: pType = new T[size];
59: for (int i = 0; i<size; i++)
60: pType[i] = 0;
61: }
62:
63: // copy constructor
64: template <class T>
65: Array<T>::Array(const Array &rhs)
66: {
67: itsSize = rhs.GetSize();
68: pType = new T[itsSize];
69: for (int i = 0; i<itsSize; i++)
70: pType[i] = rhs[i];
71: }
72:
73: // operator=
74: template <class T>
75: Array<T>& Array<T>::operator=(const Array &rhs)
76: {
77: if (this == &rhs)
78: return *this;
79: delete [] pType;
80: itsSize = rhs.GetSize();
81: pType = new T[itsSize];
82: for (int i = 0; i<itsSize; i++)
83: pType[i] = rhs[i];
84: return *this;
85: }
86:
87: // driver program
88: int main()
89: {
90: Array<int> theArray; // an array of integers
91: Array<Animal> theZoo; // an array of Animals
92: Animal *pAnimal;
93:
94: // fill the arrays
95: for (int i = 0; i < theArray.GetSize(); i++)
96: {
97: theArray[i] = i*2;
98: pAnimal = new Animal(i*3);
99: theZoo[i] = *pAnimal;
100: delete pAnimal;
101: }
102: // print the contents of the arrays
103: for (int j = 0; j < theArray.GetSize(); j++)
104: {
105: cout << "theArray[" << j << "]:\t";
106: cout << theArray[j] << "\t\t";
107: cout << "theZoo[" << j << "]:\t";
108: theZoo[j].Display();
109: cout << endl;
110: }
111:
112: for (int k = 0; k < theArray.GetSize(); k++)
113: delete &theZoo[j];
114: return 0;
<TT>115: }</TT>
Output: theArray[0]: 0 theZoo[0]: 0
theArray[1]: 2 theZoo[1]: 3
theArray[2]: 4 theZoo[2]: 6
theArray[3]: 6 theZoo[3]: 9
theArray[4]: 8 theZoo[4]: 12
theArray[5]: 10 theZoo[5]: 15
theArray[6]: 12 theZoo[6]: 18
theArray[7]: 14 theZoo[7]: 21
theArray[8]: 16 theZoo[8]: 24
theArray[9]: 18 theZoo[9]: 27
</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>Lines 8 to 26 provide a stripped-down
<TT>Animal</TT> class, created here so that there are objects of a user-defined type
to add to the array.<BR>
<BR>
Line 29 declares that what follows is a template, and that the parameter to the template
is a type, designated as <TT>T</TT>. The <TT>Array</TT> class has two constructors
as shown, the first of which takes a size and defaults to the constant integer <TT>DefaultSize</TT>.</P>
<P>The assignment and offset operators are declared, with the latter declaring both
a <TT>const</TT> and a non-<TT>const</TT> variant. The only accessor provided is
<TT>GetSize()</TT>, which returns the size of the array.</P>
<P>One can certainly imagine a fuller interface, and, for any serious <TT>Array</TT>
program, what has been supplied here would be inadequate. At a minimum, operators
to remove elements, to expand the array, to pack the array, and so forth would be
required.</P>
<P>The private data consists of the size of the array and a pointer to the actual
in-memory array of objects.
<H3 ALIGN="CENTER"><A NAME="Heading12"></A><FONT COLOR="#000077">Template Functions</FONT></H3>
<P>If you want to pass an array object to a function, you must pass a particular
instance of the array, not a template. Therefore, if <TT>SomeFunction()</TT> takes
an integer array as a parameter, you may write</P>
<PRE><FONT COLOR="#0066FF">void SomeFunction(Array<int>&); // ok
</FONT></PRE>
<P>but you may not write</P>
<PRE><FONT COLOR="#0066FF">void SomeFunction(Array<T>&); // error!
</FONT></PRE>
<P>because there is no way to know what a <TT>T&</TT> is. You also may not write</P>
<PRE><FONT COLOR="#0066FF">void SomeFunction(Array &); // error!
</FONT></PRE>
<P>because there is no class <TT>Array</TT>--only the template and the instances.</P>
<P>To accomplish the more general approach, you must declare a template function.</P>
<PRE><FONT COLOR="#0066FF">template <class T>
void MyTemplateFunction(Array<T>&); // ok
</FONT></PRE>
<P>Here the function <TT>MyTemplateFunction()</TT> is declared to be a template function
by the declaration on the top line. Note that template functions can have any name,
just as other functions can.</P>
<P>Template functions can also take instances of the template, in addition to the
parameterized form. The following is an example:</P>
<PRE><FONT COLOR="#0066FF">template <class T>
void MyOtherFunction(Array<T>&, Array<int>&); // ok
</FONT></PRE>
<P>Note that this function takes two arrays: a parameterized array and an array of
integers. The former can be an array of any object, but the latter is always an array
of integers.
<H3 ALIGN="CENTER"><A NAME="Heading13"></A><FONT COLOR="#000077">Templates and Friends</FONT></H3>
<P>Template classes can declare three types of friends:
<UL>
<LI>A non-template friend class or function.
<P>
<LI>A general template friend class or function.
<P>
<LI>A type-specific template friend class or function.
</UL>
<H4 ALIGN="CENTER"><A NAME="Heading14"></A><FONT COLOR="#000077">Non-Template Friend
Classes and Functions</FONT></H4>
<P>It is possible to declare any class or function to be a friend to your template
class. Each instance of the class will treat the friend properly, as if the declaration
of friendship had been made in that particular instance. Listing 19.3 adds a trivial
friend function, <TT>Intrude()</TT>, to the template definition of the <TT>Array</TT>
class, and the driver program invokes <TT>Intrude()</TT>. Because it is a friend,
<TT>Intrude()</TT> can then access the private data of the <TT>Array</TT>. Because
this is not a template function, it can only be called on <TT>Array</TT>s of <TT>int</TT>.
<BLOCKQUOTE>
<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>To use Listing 19.3, copy lines
1-26 of Listing 19.2 after line 1 of this listing, and then copy lines 51-86 of Listing
19.2 after line 37 of this listing.
<HR>
</BLOCKQUOTE>
<P><A NAME="Heading15"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 19.3. Non-template
friend function.</B></FONT>
<PRE><FONT COLOR="#0066FF">1: // Listing 19.3 - Type specific friend functions in templates
2:
3: template <class T> // declare the template and the parameter
4: class Array // the class being parameterized
5: {
6: public:
7: // constructors
8: Array(int itsSize = DefaultSize);
9: Array(const Array &rhs);
10: ~Array() { delete [] pType; }
11:
12: // operators
13: Array& operator=(const Array&);
14: T& operator[](int offSet) { return pType[offSet]; }
15: const T& operator[](int offSet) const
16: { return pType[offSet]; }
17: // accessors
18: int GetSize() const { return itsSize; }
19:
20: // friend function
21: friend void Intrude(Array<int>);
22:
23: private:
24: T *pType;
25: int itsSize;
26: };
27:
28: // friend function. Not a template, can only be used
29: // with int arrays! Intrudes into private data.
30: void Intrude(Array<int> theArray)
31: {
32: cout << "\n*** Intrude ***\n";
33: for (int i = 0; i < theArray.itsSize; i++)
34: cout << "i: " << theArray.pType[i] << endl;
35: cout << "\n";
36: }
37:
38: // driver program
39: int main()
40: {
41: Array<int> theArray; // an array of integers
42: Array<Animal> theZoo; // an array of Animals
43: Animal *pAnimal;
44:
45: // fill the arrays
46: for (int i = 0; i < theArray.GetSize(); i++)
47: {
48: theArray[i] = i*2;
49: pAnimal = new Animal(i*3);
50: theZoo[i] = *pAnimal;
51: }
52:
53: int j, k;
54: for (j = 0; j < theArray.GetSize(); j++)
55: {
56: cout << "theZoo[" << j << "]:\t";
57: theZoo[j].Display();
58: cout << endl;
59: }
60: cout << "Now use the friend function to ";
61: cout << "find the members of Array<int>";
62: Intrude(theArray);
63:
63: // return the allocated memory before the arrays are destroyed.
64: for (k = 0; k < theArray.GetSize(); k++)
65: delete &theZoo[j];
66:
67: cout << "\n\nDone.\n";
68: return 0;
<TT>69: }</TT></FONT>
<FONT COLOR="#0066FF">
Output: theZoo[0]: 0
theZoo[1]: 3
theZoo[2]: 6
theZoo[3]: 9
theZoo[4]: 12
theZoo[5]: 15
theZoo[6]: 18
theZoo[7]: 21
theZoo[8]: 24
theZoo[9]: 27
Now use the friend function to find the members of Array<int>
*** Intrude ***
i: 0
i: 2
i: 4
i: 6
i: 8
i: 10
i: 12
i: 14
i: 16
i: 18
Done.
</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis: </B></FONT>The declaration of the <TT>Array</TT>
template has been extended to include the friend function <TT>Intrude()</TT>. This
declares that every instance of an array will consider <TT>Intrude()</TT> to be a
friend function; thus, <TT>Intrude()</TT> will have access to the private member
data and functions of the array instance.<BR>
<BR>
On line 33, <TT>Intrude()</TT> accesses <TT>itsSize</TT> directly, and on line 34
it accesses <TT>pType</TT> directly. This trivial use of these members was unnecessary
because the <TT>Array</TT> class provides public accessors for this data, but it
serves to demonstrate how friend functions can be declared with templates.
<H4 ALIGN="CENTER"><A NAME="Heading17"></A><FONT COLOR="#000077">General Template
Friend Class or Function</FONT></H4>
<P>It would be helpful to add a display operator to the <TT>Array</TT> class. One
approach would be to declare a display operator for each possible type of <TT>Array</TT>,
but this would undermine the whole point of having made <TT>Array</TT> a template.</P>
<P>What is needed is an insertion operator that works for any possible type of <TT>Array</TT>.</P>
<PRE><FONT COLOR="#0066FF">ostream& operator<< (ostream& Array<T>&);
</FONT></PRE>
<P>To make this work, we need to declare <TT>operator<<</TT> to be a template
function.</P>
<PRE><FONT COLOR="#0066FF">template <class T> ostream& operator<< (ostream&, Array<T>&)
</FONT></PRE>
<P>Now that <TT>operator<<</TT> is a template function, you need only to provide
an implementation. Listing 19.4 shows the <TT>Array</TT> template extended to include
this declaration and provides the implementation for the <TT>operator<<</TT>.
<BLOCKQUOTE>
<P>
<HR>
<FONT COLOR="#000077"><B>NOTE: </B></FONT>To compile this listing, copy lines 8-26
of Listing 19.2 and insert them between lines 3 and 4. Also copy lines 51-86 of Listing
19.2 and insert them between lines 37 and 38.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -