190 likes | 294 Views
CS240 Computer Science II. Function and Class Templates (Based on Deitel) Dr. Erh-Wen Hu. Template Definition. template template ( tem’plət, tem’plāt ) noun 1. In an application package, an overlay for the keyboard that identifies keys and key combinations.
E N D
CS240 Computer Science II Function and Class Templates (Based on Deitel) Dr. Erh-Wen Hu
Template Definition • templatetemplate (tem’plət, tem’plāt) noun • 1.In an application package, an overlay for the keyboard that identifies keys and key combinations. • 2.In image processing, a pattern that can be used to identify or match a scanned image. • 3.In spreadsheet programs, a predesigned spreadsheet that contains formulas, labels, and other elements. • 4.In MS-DOS, a small portion of memory that holds the most recently typed MS-DOS command. • 5.In word processing and desktop publishing programs, a predesigned document that contains formatting and, in many cases, generic text.
C/C++ Template Definition • A single segment that performs identical operations on different data types. Based on the argument types in a function call, the compiler generates separate object-code functions to handle each type of calls appropriately. • The code segment allows the programmer to specify an entire range of related/overloaded functions or classes; the former is known as template functions, the latter template classes. • Examples: sort function template for an array allows array of any data type (int, float, etc.) to be sorted and stack class templeate allows operations of stack-of-int, stack-of-double, etc.
Syntax: function template definition • Funnction template begins with template<class T> Or templeate< class elementype> Or template<class bordertype, class filltype> • The formal parameters (system or user defined) can be used to specify the types of arguments to the function, the return type of a function, and to declare variables within the function.
Example: a function template // Fig 12.2: fig12_02.cpp // Using template functions #include <iostream.h> template< class T > void printArray( const T *array, const int count ) { for ( int i = 0; i < count; i++ ) cout << array[ i ] << " "; cout << endl; }
Example: a function template (continued) int main() { const int aCount = 5, bCount = 7, cCount = 6; int a[ aCount ] = { 1, 2, 3, 4, 5 }; double b[ bCount ] = { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7 }; char c[ cCount ] = "HELLO"; // 6th position for null cout << "Array a contains:" << endl; printArray( a, aCount ); // integer template function // a is of int * type cout << "Array b contains:" << endl; printArray( b, bCount ); // double template function // b is of double * type cout << "Array c contains:" << endl; printArray( c, cCount ); // character template function // c is of char * type return 0; }
How the above template simplify the code • Without using function template, the programmer must write the following overloaded functions: void printArray(const int *, const int); void printArray(const double *, const int); void printArray(const char *, const int);
Overloading template functions • The function templates can be overloaded with different number or types of parameters (same function name). • The compiler performs a matching process to determine what function to call when a function is invoked. (non-template functions first)
Class templates • Class is defined generically; objects of the class are defined with information of specific data type. • Example: stack (LIFO) operation is independent of data type; stack class can be defined generically without specifying the data type of the object to be pushed onto or poped from the stack.
Class template Example: stack • Identical to conventional class definition except it is preceded by: template<class T>
Class template Example: stack // Fig. 12.3: tstack1.h // Class template Stack #ifndef TSTACK1_H #define TSTACK1_H #include <iostream.h> template< class T > class Stack { public: Stack( int = 10 ); // default constructor (stack size 10) ~Stack() { delete [] stackPtr; } // destructor bool push( const T& ); // push an element onto the stack bool pop( T& ); // pop an element off the stack private: int size; // # of elements in the stack int top; // location of the top element T *stackPtr; // pointer to the stack bool isEmpty() const { return top == -1; } // utility bool isFull() const { return top == size - 1; } // functions };
Class template Example: stack (continued) // Constructor with default size 10 template< class T > Stack< T >::Stack( int s ) { size = s > 0 ? s : 10; top = -1; // Stack is initially empty stackPtr = new T[ size ]; // allocate space for elements } // Push an element onto the stack; return 1 if successful, 0 otherwise template< class T > bool Stack< T >::push( const T &pushValue ) { if ( !isFull() ) { stackPtr[ ++top ] = pushValue; // place item in Stack return true; // push successful } return false; // push unsuccessful }
Class template Example: stack (continued) // Pop an element off the stack template< class T > bool Stack< T >::pop( T &popValue ) { if ( !isEmpty() ) { popValue = stackPtr[ top-- ]; // remove item from Stack return true; // pop successful } return false; // pop unsuccessful } #endif
Class template Example: stack (continued) // Fig. 12.3: fig12_03.cpp // Test driver for Stack template #include <iostream.h> #include "tstack1.h" int main() { Stack< double > doubleStack( 5 ); double f = 1.1; cout << "Pushing elements onto doubleStack\n"; while ( doubleStack.push( f ) ) { // success true returned cout << f << ' '; f += 1.1; } cout << "\nStack is full. Cannot push " << f << "\n\nPopping elements from doubleStack\n"; while ( doubleStack.pop( f ) ) // success true returned cout << f << ' ';
Class template Example: stack (continued) cout << "\nStack is empty. Cannot pop\n"; Stack< int > intStack; int i = 1; cout << "\nPushing elements onto intStack\n"; while ( intStack.push( i ) ) { // success true returned cout << i << ' '; ++i; } cout << "\nStack is full. Cannot push " << i << "\n\nPopping elements from intStack\n"; while ( intStack.pop( i ) ) // success true returned cout << i << ' '; cout << "\nStack is empty. Cannot pop\n"; return 0; }
Observation of the example • In the main driver function, the code for doublestack and intstack operations are nearly identical, suggesting opportunity to use a function template, which is illustrated in the following example.
Example: passing a stack template object to a function template // Fig. 12.4: fig12_04.cpp // Test driver for Stack template. // Function main uses a function template to manipulate // objects of type Stack< T >. #include <iostream.h> #include "tstack1.h" // Function template to manipulate Stack< T > template< class T > void testStack( Stack< T > &theStack, // reference to the Stack< T > T value, // initial value to be pushed T increment, // increment for subsequent values const char *stackName ) // name of the Stack < T > object { cout << "\nPushing elements onto " << stackName << '\n'; while ( theStack.push( value ) ) { // success true returned cout << value << ' '; value += increment; }
Example: passing a stack template object to a function template (continued) cout << "\nStack is full. Cannot push " << value << "\n\nPopping elements from " << stackName << '\n'; while ( theStack.pop( value ) ) // success true returned cout << value << ' '; cout << "\nStack is empty. Cannot pop\n"; } int main() { Stack< double > doubleStack( 5 ); Stack< int > intStack; testStack( doubleStack, 1.1, 1.1, "doubleStack" ); testStack( intStack, 1, 1, "intStack" ); return 0; }
Programming assignment • Chapter 12: page 664, problem 12.8