📄 ch19.htm
字号:
18: // friend operators19: friend ostream& operator<< (ostream&, const Animal&);20:21: private:22: int itsWeight;23: };24:25: // extraction operator for printing animals26: 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)\n";37: }38:39: Animal::Animal():40: itsWeight(0)41: {42: // cout << "Animal()\n";43: }44:45: Animal::~Animal()46: {47: // cout << "Destroyed an animal...\n";48: }49:50: template <class T> // declare the template and the parameter51: class Array // the class being parameterized52: {53: public:54: Array(int itsSize = DefaultSize);55: Array(const Array &rhs);56: ~Array() { delete [] pType; }57:58: Array& operator=(const Array&);59: T& operator[](int offSet) { return pType[offSet]; }60: const T& operator[](int offSet) const 61: { return pType[offSet]; }62: int GetSize() const { return itsSize; }6364: // friend function65: friend ostream& operator<< (ostream&, const Array<T>&);66:67: private:68: T *pType;69: int itsSize;70: };71:70: template <class T>72: ostream& operator<< (ostream& output, const Array<T>& theArray)73: {74: for (int i = 0; i<theArray.GetSize(); i++)75: output << "[" << i << "] " << theArray[i] << endl;76: return output;77: }78:79: void IntFillFunction(Array<int>& theArray);80: void AnimalFillFunction(Array<Animal>& theArray);81: enum BOOL {FALSE, TRUE};82:84: int main()85: {86: Array<int> intArray;87: Array<Animal> animalArray;88: IntFillFunction(intArray);87: AnimalFillFunction(animalArray);89: cout << "intArray...\n" << intArray;90: cout << "\nanimalArray...\n" << animalArray << endl;91: return 0;92: }93:94: void IntFillFunction(Array<int>& theArray)95: {96: BOOL Stop = FALSE;97: int offset, value;98: while (!Stop)99: {100: cout << "Enter an offset (0-9) ";101: cout << "and a value. (-1 to stop): " ;102: cin >> offset >> value;103: if (offset < 0)104: break;105: if (offset > 9)106: {107: cout << "***Please use values between 0 and 9.***\n";108: continue;109: }110: theArray[offset] = value;111: }112: }113:114:115: void AnimalFillFunction(Array<Animal>& theArray)116: {117: Animal * pAnimal;118: for (int i = 0; i<theArray.GetSize(); i++)119: {120: pAnimal = new Animal;121: pAnimal->SetWeight(i*100);122: theArray[i] = *pAnimal;123: delete pAnimal; // a copy was put in the array124: }<TT>125: }</TT></FONT><FONT COLOR="#0066FF">Output: Enter an offset (0-9) and a value. (-1 to stop): 1 10Enter an offset (0-9) and a value. (-1 to stop): 2 20Enter an offset (0-9) and a value. (-1 to stop): 3 30Enter an offset (0-9) and a value. (-1 to stop): 4 40Enter an offset (0-9) and a value. (-1 to stop): 5 50Enter an offset (0-9) and a value. (-1 to stop): 6 60Enter an offset (0-9) and a value. (-1 to stop): 7 70Enter an offset (0-9) and a value. (-1 to stop): 8 80Enter an offset (0-9) and a value. (-1 to stop): 9 90Enter an offset (0-9) and a value. (-1 to stop): 10 10***Please use values between 0 and 9.***Enter an offset (0-9) and a value. (-1 to stop): -1 -1intArray:...[0] 0[1] 10[2] 20[3] 30[4] 40[5] 50[6] 60[7] 70[8] 80[9] 90animalArray:...[0] 0[1] 100[2] 200[3] 300[4] 400[5] 500[6] 600[7] 700[8] 800[9] 900</FONT></PRE><P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>Most of the <TT>Array</TT>class implementation is left out to save space. The <TT>Animal</TT> class is declaredon lines 6-23. Although this is a stripped-down and simplified class, it does provideits own insertion operator (<TT><<</TT>) to allow the printing of <TT>Animal</TT>s.Printing simply prints the current weight of the <TT>Animal</TT>.<BR>Note that <TT>Animal</TT> has a default constructor. This is necessary because, whenyou add an object to an array, the object's default constructor is used to createthe object. This creates some difficulties, as you'll see.</P><P>On line 79, the function <TT>IntFillFunction()</TT> is declared. The prototypeindicates that this function takes an integer array. Note that this is not a templatefunction. <TT>IntFillFunction()</TT> expects only one type of an array--an integerarray. 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, becausefilling an array of integers does not have to be accomplished in the same way asfilling 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 constructorsand destructor in Listing 19.5, you'll find there are unanticipated extra constructionsand 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 valueof 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 theright-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 alreadyproperly initialized. However, you can't remove this line, because integers are notautomatically initialized to a value of <TT>0</TT>. The solution is to teach thetemplate 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 indicatedin Listing 19.6.</P><P><A NAME="Heading25"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 19.6. Specializingtemplate 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 arrays6: class Animal7: {8: public:9: // constructors10: Animal(int);11: Animal();12: ~Animal();13:14: // accessors15: int GetWeight() const { return itsWeight; }16: void SetWeight(int theWeight) { itsWeight = theWeight; }17:18: // friend operators19: friend ostream& operator<< (ostream&, const Animal&);20:21: private:22: int itsWeight;23: };24:25: // extraction operator for printing animals26: 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 parameter51: class Array // the class being parameterized52: {53: public:54: Array(int itsSize = DefaultSize);55: Array(const Array &rhs);56: ~Array() { delete [] pType; }57:58: // operators59: 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: // accessors64: int GetSize() const { return itsSize; }65:66: // friend function67: 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 02: Enter an offset (0-9) and a value. (-1 to stop): 1 13: Enter an offset (0-9) and a value. (-1 to stop): 2 24: Enter an offset (0-9) and a value. (-1 to stop): 3 35: Enter an offset (0-9) and a value. (-1 to stop): -1 -16: animal(int) Destroyed an animal...animal(int) Destroyed an animal...animal(int) Destroyed an animal...initArray...7: [0] 08: [1] 19: [2] 210:11: animal array...12: [0] 013: [1] 1014: [2] 2015:16: Destroyed an animal...Destroyed an animal...Destroyed an animal...
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -