Latest

recent

A Type-Specific Template Friend Class or Function in C++


Although the insertion operator shown in Listing 19.4 works, it is still not quite what is needed. Because the declaration of the friend operator on line 29 declares a template, it will work for any instance of Array and any insertion operator taking an array of any type.

The insertion operator template shown in Listing 19.4 makes all instances of the insertion operator<< a friend of any instance of Array, whether the instance of the insertion operator is an integer, an Animal, or a Car. It makes no sense, however, for an Animal insertion operator to be a friend to the insertion operator for an integer array.

What is needed is for the insertion operator for an array of int to be a friend to the Array of int class, and for the insertion operator of an array of Animals to be a friend to the Array of animals instance.
To accomplish this, modify the declaration of the insertion operator on line 29 of Listing 19.4, and remove the words template <class T>. That is, change line 30 to read
friend ostream& operator<< (ostream&, Array<T>&);
This will use the type (T) declared in the template of Array. Thus, the operator<< for an integer will only work with an array of integers, and so forth.

Using Template Items

You can treat template items as you would any other type. You can pass them as parameters, either by reference or by value, and you can return them as the return values of functions, also by value or by reference. Listing 19.5 demonstrates how to pass template objects.

Listing 19.5. Passing template objects to and from functions.

1: #include <iostream.h>
2:
3: const int DefaultSize = 10;
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)\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 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: 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; }
63
64: // friend function
65: 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 array
124: }
125: }


Output: Enter an offset (0-9) and a value. (-1 to stop): 1 10
Enter an offset (0-9) and a value. (-1 to stop): 2 20
Enter an offset (0-9) and a value. (-1 to stop): 3 30
Enter an offset (0-9) and a value. (-1 to stop): 4 40
Enter an offset (0-9) and a value. (-1 to stop): 5 50
Enter an offset (0-9) and a value. (-1 to stop): 6 60
Enter an offset (0-9) and a value. (-1 to stop): 7 70
Enter an offset (0-9) and a value. (-1 to stop): 8 80
Enter an offset (0-9) and a value. (-1 to stop): 9 90
Enter 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 -1

intArray:...
[0] 0
[1] 10
[2] 20
[3] 30
[4] 40
[5] 50
[6] 60
[7] 70
[8] 80
[9] 90

animalArray:...
[0] 0
[1] 100
[2] 200
[3] 300
[4] 400
[5] 500
[6] 600
[7] 700
[8] 800
[9] 900

Analysis: Most of the Array class implementation is left out to save space. The Animal class is declared on lines 6-23. Although this is a stripped-down and simplified class, it does provide its own insertion operator (<<) to allow the printing of Animals. Printing simply prints the current weight of the Animal.

Note that Animal 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.

On line 79, the function IntFillFunction() is declared. The prototype indicates that this function takes an integer array. Note that this is not a template function. IntFillFunction() expects only one type of an array--an integer array. Similarly, on line 80, AnimalFillFunction() is declared to take an Array of Animal.

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 Animals.
A Type-Specific Template Friend Class or Function in C++ Reviewed by 1000sourcecodes on 23:53 Rating: 5
Powered by Blogger.