Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 40 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
40
Dung lượng
465,22 KB
Nội dung
680 Templates Display 16.8 Interface for the Template Class PFArrayBak (part 2 of 2) 10 template<class T> 11 class PFArrayBak : public PFArray<T> 12 { 13 public: 14 PFArrayBak( ); 15 //Initializes with a capacity of 50. 16 PFArrayBak(int capacityValue); 17 PFArrayBak(const PFArrayBak<T>& Object); 18 void backup( ); 19 //Makes a backup copy of the partially filled array. 20 void restore( ); 21 //Restores the partially filled array to the last saved version. 22 //If backup has never been invoked, this empties the partially 23 //filled array. 24 PFArrayBak<T>& operator =(const PFArrayBak<T>& rightSide); 25 virtual ~PFArrayBak( ); 26 private: 27 T *b; //for a backup of main array. 28 int usedB; //backup for inherited member variable used. 29 }; 30 }// PFArraySavitch 31 #endif //PFARRAY_H Display 16.9 Implementation for the Template Class PFArrayBak (part 1 of 3) 1 //This is the file pfarraybak.cpp. 2 //This is the implementation for the template class PFArrayBak. The 3 //interface for the template class PFArrayBak is in the file pfarraybak.h. 4 #include "pfarraybak.h" 5 #include <iostream> 6 using std::cout; 7 namespace PFArraySavitch 8 { 9 template<class T> 10 PFArrayBak<T>::PFArrayBak( ) : PFArray<T>( ), usedB(0) 16_CH16.fm Page 680 Monday, August 18, 2003 1:04 PM Templates and Inheritance 681 Display 16.9 Implementation for the Template Class PFArrayBak (part 2 of 3) 11 { 12 b = new T[getCapacity( )]; 13 } 14 template<class T> 15 PFArrayBak<T>::PFArrayBak(int capacityValue) 16 : PFArray<T>(capacityValue), usedB(0) 17 { 18 b = new T[getCapacity( )]; 19 } 20 template<class T> 21 PFArrayBak<T>::PFArrayBak(const PFArrayBak<T>& oldObject) 22 : PFArray<T>(oldObject), usedB(0) 23 { 24 b = new T[getCapacity( )]; 25 usedB = oldObject.getNumberUsed(); 26 for (int i = 0; i < usedB; i++) 27 b[i] = oldObject.b[i]; 28 } 29 template<class T> 30 void PFArrayBak<T>::backup( ) 31 { 32 usedB = getNumberUsed( ); 33 for (int i = 0; i < usedB; i++) 34 b[i] = operator[](i); 35 } 36 template<class T> 37 void PFArrayBak<T>::restore( ) 38 { 39 emptyArray( ); 40 for (int i = 0; i < usedB; i++) 41 addElement(b[i]); 42 } 43 template<class T> 44 PFArrayBak<T>& PFArrayBak<T>::operator =(const PFArrayBak<T>& rightSide) 45 { 46 PFArray<T>::operator =(rightSide); 47 if (getCapacity( ) != rightSide.getCapacity( )) 48 { 49 delete [] b; 50 b = new T[rightSide.getCapacity( )]; 51 } 16_CH16.fm Page 681 Monday, August 18, 2003 1:04 PM 682 Templates Display 16.9 Implementation for the Template Class PFArrayBak (part 3 of 3) 52 usedB = rightSide.usedB; 53 for (int i = 0; i < usedB; i++) 54 b[i] = rightSide.b[i]; 55 return *this; 56 } 57 template<class T> 58 PFArrayBak<T>::~PFArrayBak( ) 59 { 60 delete [] b; 61 } 62 }// PFArraySavitch Display 16.10 Demonstration Program for Template Class PFArrayBak (part 1 of 2) 1 //Program to demonstrate the template class PFArrayBak. 2 #include <iostream> 3 #include <string> 4 using std::cin; 5 using std::cout; 6 using std::endl; 7 using std::string; 8 #include "pfarraybak.h" 9 #include "pfarray.cpp" 10 #include "pfarraybak.cpp" 11 using PFArraySavitch::PFArrayBak; 12 int main( ) 13 { 14 int cap; 15 cout << "Enter capacity of this super array: "; 16 cin >> cap; 17 PFArrayBak<string> a(cap); 18 cout << "Enter " << cap << " strings\n"; 19 cout << "separated by blanks.\n"; 20 string next; 21 for (int i = 0; i < cap; i++) 22 { 23 cin >> next; 24 a.addElement(next); 25 } Do not forget to include the implementation of the base class template 16_CH16.fm Page 682 Monday, August 18, 2003 1:04 PM Templates and Inheritance 683 Display 16.10 Demonstration Program for Template Class PFArrayBak (part 2 of 2) 26 int count = a.getNumberUsed( ); 27 cout << "The following " << count 28 << " strings read and stored:\n"; 29 int index; 30 for (index = 0; index < count; index++) 31 cout << a[index] << " "; 32 cout << endl; 33 cout << "Backing up array.\n"; 34 a.backup( ); 35 cout << "Emptying array.\n"; 36 a.emptyArray( ); 37 cout << a.getNumberUsed( ) 38 << " strings are now stored in the array.\n"; 39 cout << "Restoring array.\n"; 40 a.restore( ); 41 count = a.getNumberUsed( ); 42 cout << "The following " << count 43 << " strinss are now stored:\n"; 44 for (index = 0; index < count; index++) 45 cout << a[index] << " "; 46 cout << endl; 47 cout << "End of demonstration.\n"; 48 return 0; 49 } S AMPLE D IALOGUE Enter capacity of this super array: 3 Enter 3 strings separated by blanks. I love you The following 3 strings read and stored: I love you Backing up array. Emptying array. 0 strings are now stored in the array. Restoring array. The following 3 strings are now stored: I love you End of demonstration. 16_CH16.fm Page 683 Monday, August 18, 2003 1:04 PM 684 Templates Self-Test Exercises 13. Is it legal for a derived template class to start as shown below? The template class TwoDimPFArrayBak is designed to be a two-dimensional partially filled array with backup. template<class T> class TwoDimPFArrayBak : public PFArray< PFArray<T> > { public: TwoDimPFArrayBak( ); Note that the space in < PFArray<T> > is important, or at least the last space is. If the space between the next-to-last > and the last > is omitted, then the compiler may interpret >> to be the extraction operator used for input in expressions like cin >> n; rather than interpreting it as a nested < >. 14. Give the heading for the default (zero-argument) constructor for the class TwoDimPFAr- rayBak given in Self-Test Exercise 13. (Assume all instance variables are initialized in the body of the constructor definition, so you are not being ask to do that.) ■ Using function templates, you can define functions that have a parameter for a type. ■ Using class templates, you can define a class with a type parameter for subparts of the class. ■ The predefined vector and basic_string classes are actually template classes. ■ You can define a template class that is a derived class of a template base class. ANSWERS TO SELF-TEST EXERCISES 1. Function declaration: template<class T> T maximum(T first, T second); //Precondition: The operator < is defined for the type T. //Returns the maximum of first and second. Definition: template<class T> T maximum(T first, T second) { if (first < second) return second; else return first; } Chapter Summary 16_CH16.fm Page 684 Monday, August 18, 2003 1:04 PM Answers to Self-Test Exercises 685 2. Function declaration: template<class T> T absolute(T value); //Precondition: The expressions x < 0 and -x are defined //whenever x is of type T. //Returns the absolute value of its argument. Definition: template<class T> T absolute(T value) { if (value < 0) return -value; else return value; } 3. Templates provide a facility to allow the definition of functions and classes that have parameters for type names. 4. e. Any type, whether a primitive type (provided by C++) or a type defined by the user (a class or struct type, an enum type, or a type defined array, or int, float, double, etc.), but T must be a type for which the code in the template makes sense. For example, for the swapValues template function (Display 16.1), the type T must have a correctly working assignment operator. 5. The function declaration and function definition are given below. They are basically iden- tical to those for the versions given in Display 5.6 except that two instances of int are changed to T in the parameter list. Function declaration: template<class T> int search(const T a[], int numberUsed, T target); //Precondition: numberUsed is <= the declared size of a. //Also, a[0] through a[numberUsed -1] have values. //Returns the first index such that a[index] == target, //provided there is such an index, otherwise returns -1. Definition: template<class T> int search(const T a[], int numberUsed, T target) { int index = 0; bool found = false; while ((!found) && (index < numberUsed)) if (target == a[index]) found = true; else 16_CH16.fm Page 685 Monday, August 18, 2003 1:04 PM 686 Templates index++; if (found) return index; else return -1; } 6. Function overloading only works for types for which an overloading is provided. (Over- loading may work for types that automatically convert to some type for which an overload- ing is provided, but it may not do what you expect.) The template solution will work for any type that is defined at the time of invocation, provided that the template function body makes sense for that type. 7. No, you cannot use an array with base type DayOfYear with the template function sort because the < operator is not defined on values of type DayOfYear. (If you overload < , as we discussed in Chapter 8, to give a suitable ordering on values of type DayOfYear, then you can use an array with base type DayOfYear with the template function sort. For example, you might overload < so it means one date comes before the other on the calendar and then sort an array of dates by calendar ordering.) 8. a contains: 0 1 2 b contains: 0 100 200 c contains: 0 1 2 After swapping a and b, and changing b: a contains: 0 100 200 b contains: 42 1 2 c contains: 42 1 2 Note that before swapValues(a, b); c is an alias (another name for) the array a. After swapValues(a, b); c is an alias for b. Although the values of a and b are in some sense swapped, things are not as simple as you might have hoped. With pointer variables, there can be side effects of using swapValues. The point illustrated here is that the assignment operator is not as well behaved as you might want on array pointers and so the template swapValues does not work as you might want with variables that are pointers to arrays. The assignment operator does not do ele- ment by element swapping but merely swaps two pointers. So, the swapValues function used with pointers to arrays simply swaps two pointers. It might be best to not use swapValues with pointers to arrays (or any other pointers), unless you are very aware of how it behaves on the pointers. The swapValues template function used with a type T is only as good, or as bad, as the assignment operator is on type T. 16_CH16.fm Page 686 Monday, August 18, 2003 1:04 PM Answers to Self-Test Exercises 687 9. Since the type can be any type at all, there are no natural candidates for the default initial- ization values. So this constructor does nothing, but it does allow you to declare (uninitial- ized) objects without giving any constructor arguments. template<class T> Pair<T>::Pair( ) { //Do nothing. } 10. int addUp(const Pair<int>& thePair) { return (thePair.getFirst( ) + thePair.getSecond( )); } 11. template<class T> T addUp(const Pair<T>& thePair) { return (thePair.getFirst( ) + thePair.getSecond( )); } 12. You add the following to the public section of the template class definition of PFArray: friend void showData(PFArray<T> theObject); //Displays the data in theObject to the screen. //Assumes that << is defined for values of type T. You also need to add a function template definition of showData. One possible definition is as follows: namespace PFArraySavitch { template<class T> void showData(PFArray< T > theObject) { for (int i = 0; i < theObject.used; i++) cout << theObject[i] << endl; } }//PFArraySavitch 13. Yes, it is perfectly legal. There are other, possibly preferable, ways to accomplish the same thing, but this is legal and not even crazy. 14. template<class T> TwoDimPFArrayBak<T>::TwoDimPFArrayBak( ) : PFArray< PFArray<T> >( ) 16_CH16.fm Page 687 Monday, August 18, 2003 1:04 PM 688 Templates PROGRAMMING PROJECTS 1. Write a template version of the iterative binary search from Display 13.8. Specify require- ments on the template parameter type. Discuss the requirements on the template parame- ter type. 2. Write a template version of the recursive binary search from Display 13.6. Specify require- ments on the template parameter type. Discuss the requirements on the template parame- ter type. 3. The template sort routine Display 16.3 is based on an algorithm called the selection sort Another related sorting algorithm is called insertion sort. The insertion sort algorithm is the sort method used to sort a Bridge hand. Consider each element in turn, inserting it into its proper place among the elements at the start of the array that are already sorted. The ele- ment being considered is inserted by moving the larger elements “to the right” to make space and inserting the vacated place. For example, the following shows the steps in a selec- tion sort of an array of ints a. The values of a[0] through a[4] are given on each line. The asterisk marks the boundary between the sorted and unsorted portions of the array. 2 * 5 3 4 2 5 * 3 4 2 3 5 * 4 2 3 4 5 * First, write an insertion sort function that works for ints. Next, write the template version of this sort function. Finally, test thoroughly using several primitive types, and test using a type you create with the minimal machinery necessary to use the sort routine. 16_CH16.fm Page 688 Monday, August 18, 2003 1:04 PM For additional online Programming Projects, click the CodeMate icons below. 1.7 17 Linked Data Structures 17.1 NODES AND LINKED LISTS 691 Nodes 691 Linked Lists 696 Inserting a Node at the Head of a List 698 Pitfall: Losing Nodes 700 Inserting and Removing Nodes Inside a List 702 Pitfall: Using the Assignment Operator with Dynamic Data Structures 706 Searching a Linked List 706 Example: Template Version of Linked List Tools 711 17.2 LINKED LIST APPLICATIONS 715 Example: A Stack Template Class 715 Example: A Queue Template Class 722 Tip: A Comment on Namespaces 725 Friend Classes and Similar Alternatives 726 17.3 ITERATORS 729 Pointers as Iterators 729 Iterator Classes 730 Example: An Iterator Class 731 17.4 TREES 738 Tree Properties 739 Example: A Tree Template Class 742 CHAPTER SUMMARY 747 ANSWERS TO SELF-TEST EXERCISES 747 PROGRAMMING PROJECTS 754 17_CH17.fm Page 689 Tuesday, August 19, 2003 10:22 AM [...]... list shown in Display 17.2 This last node has the word NULL written where there should be a pointer In Display 17.1 we filled this position with the phrase “end marker,” but “end marker” is not a C++ expression In C++ programs we use the constant NULL as a marker to signal the end of a linked list (or the end of any other kind of linked data structure) NULL is typically used for two different (but often... ListNode is still circular The definition of the type ListNode uses the type name ListNode to define the member variable link There is nothing wrong with this particular circularity, which is allowed in C++ One indication that this definition is not logically inconsistent is the fact that you can draw pictures, such as Display 17.1 , that represent such structures We now have pointers inside structs and... 17_CH17.fm Page 693 Tuesday, August 19, 2003 10:22 AM Nodes and Linked Lists 693 (and that would produce an error) The next paragraph describes a shortcut notation that can avoid this worry about parentheses C++ has an operator that can be used with a pointer to simplify the notation for specifying the members of a struct or a class Chapter 10 introduced the arrow operator, ->, but we have not used it extensively... Structures that can point to other nodes of the same type Note that pointers point to the entire node, not to the individual items (such as 10 or "rolls") that are inside the node Nodes are implemented in C++ as structs or classes For example, the struct type definitions for a node of the type shown in Display 17.1 , along with the type definition for a pointer to such nodes, can be as follows: struct ListNode... libraries, such as and , so you should use an include directive with either , , or some other suitable library when you use NULL The definition of NULL is handled by the C++ preprocessor, which 17_CH17.fm Page 695 Tuesday, August 19, 2003 10:22 AM Nodes and Linked Lists 695 replaces NULL with 0 Thus, the compiler never actually sees “NULL” and so there are no namespace... are retrieved in the opposite order to which they were placed in the stack Stacks are used for many language processing tasks Chapter 13 discussed how the computer system uses a stack to keep track of C++ function calls However, here we will only be concerned with one very simple application Our goal in this example is to show how you can use the linked list techniques to implement specific data structures, . absolute( T value); //Precondition: The expressions x < 0 and -x are defined //whenever x is of type T. //Returns the absolute value of its argument. Definition: template<class T> T absolute( T. Display 17.1 we filled this position with the phrase “end marker,” but “end marker” is not a C++ expression. In C++ programs we use the constant NULL as a marker to signal the end of a linked list. (such as 10 or "rolls" ) that are inside the node. Nodes are implemented in C++ as struct s or classes. For example, the struct type definitions for a node of the