📄 ch19.htm
字号:
5: {
6: public:
7: // constructors
8: Array(int itsSize = DefaultSize);
9: Array(const Array &rhs);
10: ~Array() { delete [] pType; itsNumberArrays--; }
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: static int GetNumberArrays() { return itsNumberArrays; }
20:
21: // friend function
22: friend ostream& operator<< (ostream&, const Array<T>&);
23:
24: private:
25: T *pType;
26: int itsSize;
27: static int itsNumberArrays;
28: };
29:
30: template <class T>
31: int Array<T>::itsNumberArrays = 0;
32:
33: template <class T>
34: Array<T>::Array(int size = DefaultSize):
35: itsSize(size)
36: {
37: pType = new T[size];
38: for (int i = 0; i<size; i++)
39: pType[i] = (T)0;
40: itsNumberArrays++;
41: }
42:
43: template <class T>
44: Array<T>& Array<T>::operator=(const Array &rhs)
45: {
46: if (this == &rhs)
47: return *this;
48: delete [] pType;
49: itsSize = rhs.GetSize();
50: pType = new T[itsSize];
51: for (int i = 0; i<itsSize; i++)
52: pType[i] = rhs[i];
53: }
54:
55: template <class T>
56: Array<T>::Array(const Array &rhs)
57: {
58: itsSize = rhs.GetSize();
59: pType = new T[itsSize];
60: for (int i = 0; i<itsSize; i++)
61: pType[i] = rhs[i];
62: itsNumberArrays++;
63: }
64:
65:
66: template <class T>
67: ostream& operator<< (ostream& output, const Array<T>& theArray)
68: {
69: for (int i = 0; i<theArray.GetSize(); i++)
70: output << "[" << i << "] " << theArray[i] << endl;
71: return output;
72: }
73:
74:
75: Array<Animal>::Array(int AnimalArraySize):
76: itsSize(AnimalArraySize)
77: {
78: pType = new T[AnimalArraySize];
79: itsNumberArrays++;
80: }
81:
82: int main()
83: {
84:
85: cout << Array<int>::GetNumberArrays() << " integer arrays\n";
86: cout << Array<Animal>::GetNumberArrays();
87 cout << " animal arrays\n\n";
88: Array<int> intArray;
89: Array<Animal> animalArray;
90:
91: cout << intArray.GetNumberArrays() << " integer arrays\n";
92: cout << animalArray.GetNumberArrays();
93: cout << " animal arrays\n\n";
93:
94: Array<int> *pIntArray = new Array<int>;
95:
96: cout << Array<int>::GetNumberArrays() << " integer arrays\n";
97: cout << Array<Animal>::GetNumberArrays();
98: cout << " animal arrays\n\n";
98:
99: delete pIntArray;
100:
101: cout << Array<int>::GetNumberArrays() << " integer arrays\n";
102: cout << Array<Animal>::GetNumberArrays();
103: cout << " animal arrays\n\n";
103: return 0;
<TT>104: }</TT></FONT>
<FONT COLOR="#0066FF">
Output: 0 integer arrays
0 animal arrays
1 integer arrays
1 animal arrays
2 integer arrays
1 animal arrays
1 integer arrays
1 animal arrays
</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>The declaration of the <TT>Animal</TT>
class has been left out to save space. The <TT>Array</TT> class has added the static
variable <TT>itsNumberArrays</TT> on line 27, and because this data is private, the
static public accessor <TT>GetNumberArrays()</TT> was added on line 19.<BR>
Initialization of the static data is accomplished with a full template qualification,
as shown on lines 30 and 31. The constructors of <TT>Array</TT> and the destructor
are each modified to keep track of how many arrays exist at any moment.</P>
<P>Accessing the static members is exactly like accessing the static members of any
class: You can do so with an existing object, as shown on lines 91 and 92, or by
using the full class specification, as shown on lines 85 and 86. Note that you must
use a specific type of array when accessing the static data. There is one variable
for each type.
<BLOCKQUOTE>
<P>
<HR>
<B>DO</B> use statics with templates as needed.<B> DO</B> specialize template behavior
by overriding template functions by type.<B> DO</B> use the parameters to template
functions to narrow their instances to be type-safe.
<HR>
</BLOCKQUOTE>
<H3 ALIGN="CENTER"><A NAME="Heading30"></A><FONT COLOR="#000077">The Standard Template
Library</FONT></H3>
<P>A new development in C++ is the adoption of the Standard Template Library (STL).
All the major compiler vendors now offer the STL as part of their compilers. STL
is a library of template-based container classes, including vectors, lists, queues,
and stacks. The STL also includes a number of common algorithms, including sorting
and searching.</P>
<P>The goal of the STL is to give you an alternative to reinventing the wheel for
these common requirements. The STL is tested and debugged, offers high performance,
and is free. Most important, the STL is reusable; once you understand how to use
an STL container, you can use it in all your programs without reinventing it.
<H3 ALIGN="CENTER"><A NAME="Heading31"></A><FONT COLOR="#000077">Summary</FONT></H3>
<P>Today you learned how to create and use templates. Templates are a built-in facility
of C++, used to create parameterized types--types that change their behavior based
on parameters passed in at creation. They are a way to reuse code safely and effectively.</P>
<P>The definition of the template determines the parameterized type. Each instance
of the template is an actual object, which can be used like any other object--as
a parameter to a function, as a return value, and so forth.</P>
<P>Template classes can declare three types of friend functions: non-template, general
template, and type-specific template. A template can declare static data members,
in which case each instance of the template has its own set of static data.</P>
<P>If you need to specialize behavior for some template functions based on the actual
type, you can override a template function with a particular type. This works for
member functions as well.
<H3 ALIGN="CENTER"><A NAME="Heading32"></A><FONT COLOR="#000077">Q&A</FONT></H3>
<DL>
<DD><B>Q. Why use templates when macros will do?<BR>
</B><BR>
<B>A. </B>Templates are type-safe and built into the language.<BR>
<BR>
<B>Q. What is the difference between the parameterized type of a template function
and the parameters to a normal function?<BR>
</B><BR>
<B>A.</B> A regular function (non-template) takes parameters on which it may take
action. A template function allows you to parameterize the type of a particular parameter
to the function. That is, you can pass an <TT>Array</TT> of Type to a function, and
then have the Type determined by the template instance.<BR>
<BR>
<B>Q. When do you use templates and when do you use inheritance?<BR>
</B><BR>
<B>A.</B> Use templates when all the behavior, or virtually all the behavior, is
unchanged, except in regard to the type of the item on which your class acts. If
you find yourself copying a class and changing only the type of one or more of its
members, it may be time to consider using a template.<BR>
<BR>
<B>Q. When do you use general template friend classes?<BR>
</B><BR>
<B>A.</B> When every instance, regardless of type, should be a friend to this class
or function.<BR>
<BR>
<B>Q. When do you use type-specific template friend classes or functions?<BR>
</B><BR>
<B>A.</B> When you want to establish a one-to-one relationship between two classes.
For example, <TT>array<int></TT> should match <TT>iterator<int></TT>,
but not <TT>iterator<Animal></TT>.
</DL>
<H3 ALIGN="CENTER"><A NAME="Heading33"></A><FONT COLOR="#000077">Workshop</FONT></H3>
<P>The Workshop provides quiz questions to help you solidify your understanding of
the material covered, and exercises to provide you with experience in using what
you've learned. Try to answer the quiz and exercise questions before checking the
answers in Appendix D, and make sure you understand the answers before continuing
to the next chapter.
<H4 ALIGN="CENTER"><A NAME="Heading34"></A><FONT COLOR="#000077">Quiz</FONT></H4>
<DL>
<DD><B>1.</B> What is the difference between a template and a macro?<BR>
<B><BR>
2.</B> What is the difference between the parameter in a template and the parameter
in a function?<BR>
<B><BR>
3.</B> What is the difference between a type-specific template friend class and a
general template friend class?<BR>
<B><BR>
4.</B> Is it possible to provide special behavior for one instance of a template
but not for other instances?<BR>
<B><BR>
5.</B> How many static variables are created if you put one static member into a
template class definition?
</DL>
<H4 ALIGN="CENTER"><A NAME="Heading35"></A><FONT COLOR="#000077">Exercises</FONT></H4>
<DL>
<DD><B>1.</B> Create a template based on this <TT>List</TT> class:
</DL>
<PRE><FONT COLOR="#0066FF">class List
{
private:
public:
List():head(0),tail(0),theCount(0) {}
virtual ~List();
void insert( int value );
void append( int value );
int is_present( int value ) const;
int is_empty() const { return head == 0; }
int count() const { return theCount; }
private:
class ListCell
{
public:
ListCell(int value, ListCell *cell =
):val(value),next(cell){}
int val;
ListCell *next;
};
ListCell *head;
ListCell *tail;
int theCount;
};
</FONT></PRE>
<DL>
<DD><B>2. </B>Write the implementation for the <TT>List</TT> class (non-template)
version.<BR>
<B><BR>
3.</B> Write the template version of the implementations.<BR>
<B><BR>
4.</B> Declare three list objects: a list of <TT>String</TT>s, a list of <TT>Cat</TT>s,
and a list of <TT>int</TT>s.<BR>
<B><BR>
5.</B> BUG BUSTERS: What is wrong with the following code? (Assume the <TT>List</TT>
template is defined and <TT>Cat</TT> is the class defined earlier in the book.)
</DL>
<PRE><FONT COLOR="#0066FF">List<Cat> Cat_List;
Cat Felix;
CatList.append( Felix );
cout << "Felix is " <<
( Cat_List.is_present( Felix ) ) ? "" : "not " << "present\n";
</FONT></PRE>
<DL>
<DD>HINT (this is tough): What makes <TT>Cat</TT> different from <TT>int</TT>?<BR>
<BR>
<B>6.</B> Declare friend <TT>operator==</TT> for <TT>List</TT>.<BR>
<B><BR>
7.</B> Implement friend <TT>operator==</TT> for <TT>List</TT>.<BR>
<B><BR>
8.</B> Does <TT>operator==</TT> have the same problem as in Exercise 5?<BR>
<B><BR>
9.</B> Implement a template function for <TT>swap</TT>, which exchanges two variables.
<P>
</DL>
<P ALIGN="CENTER"><A HREF="ch18.htm" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/htm/ch18.htm"><IMG SRC="BLANPREV.GIF" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/buttons/BLANPREV.GIF"
WIDTH="37" HEIGHT="37" ALIGN="BOTTOM" BORDER="0"></A><A HREF="tppmsgs/msgs0.htm#1" tppabs="http://www.mcp.com/sams"><IMG
SRC="BLANHOME.GIF" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/buttons/BLANHOME.GIF" WIDTH="37" HEIGHT="37" ALIGN="BOTTOM"
BORDER="0"></A><A HREF="index.htm" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/index.htm"><IMG SRC="BLANTOC.GIF" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/buttons/BLANTOC.GIF"
WIDTH="37" HEIGHT="37" ALIGN="BOTTOM" BORDER="0"></A><A HREF="ch20.htm" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/htm/ch20.htm"><IMG SRC="BLANNEXT.GIF" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/buttons/BLANNEXT.GIF"
WIDTH="37" HEIGHT="37" ALIGN="BOTTOM" BORDER="0"></A><A HREF="#heading1"><IMG SRC="BLANTOP.GIF" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/buttons/BLANTOP.GIF"
WIDTH="37" HEIGHT="37" ALIGN="BOTTOM" BORDER="0"></A>
</BODY>
</HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -