模板4(template)
1、Making a Function Template a Friend
The output operator needs to be a friend of both the Queue and QueueItem classes. It uses the head member of class Queue and the next and item members of class QueueItem . Our classes grant friendship to the specific instance of the output operator instantiated with the same type:
// function template declaration must precede friend declaration in QueueItem template <class T> std::ostream& operator<<(std::ostream&, const Queue<T>&); template <class Type> class QueueItem { friend class Queue<Type>; // needs access to item and next friend std::ostream& operator<< <Type> (std::ostream&, const Queue<Type>&); // ... }; template <class Type> class Queue { // needs access to head friend std::ostream& operator<< <Type> (std::ostream&, const Queue<Type>&); };
Each friend declaration grants access to the corresponding instantiation of the operator<< . That is, the output operator that prints a Queue<int> is a friend to class Queue<int> (and QueueItem<int>) . It is not a friend to any other Queue type.
2、Type Dependencies and the Output Operator
The Queue output operator<< relies on the operator<< of item to actually print each element: os << p->item << " ";
When we use p->item as an operand of the << operator, we are using the << defined for whatever type item has This code is an example of a type dependency between Queue and the element type that Queue holds. In effect, each type bound to Queue that uses the Queue output operator must itself have an output operator. There is no language mechanism to specify or enforce that dependency in the definition of Queue itself. It is legal to create a Queue for a class that does not define the output operator but it is a compile-time (or link-time) error to print a Queue holding such a type.
3、Defining a Member Template
template <class Type> class Queue { public: // construct a Queue from a pair of iterators on some sequence template <class It> Queue(It beg, It end): head(0), tail(0) { copy_elems(beg, end); } // replace current Queue by contents delimited by a pair of iterators template <class Iter> void assign(Iter, Iter); // rest of Queue class as before private: // version of copy to be used by assign to copy elements from iterator range template <class Iter> void copy_elems(Iter, Iter); };
The member declaration starts with its own template parameter list. The constructor and assign member each have a single template type parameter. These functions use that type parameter as the type for their function parameters, which are iterators denoting a range of elements to copy.
4、Defining a Member Template Outside the Class
When we define a member template outside the scope of a class template, we must include both template parameter lists:
template <class T> template <class Iter> void Queue<T>::assign(Iter beg, Iter end) { destroy(); // remove existing elements in this Queue copy_elems(beg, end); // copy elements from the input range }
When a member template is a member of a class template, then its definition must include the class-template parameters as well as its own template parameters. The class-template parameter list comes first, followed by the member's own template parameter list.
浙公网安备 33010602011771号