chapter 14 templates (樣板) chapter 14 templates (樣板)

50
Chapter 14 Chapter 14 Templates Templates 樣樣樣 () 樣樣樣 ()

Upload: evelyn-silas-clarke

Post on 13-Dec-2015

265 views

Category:

Documents


7 download

TRANSCRIPT

Page 1: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

Chapter 14 Chapter 14 TemplatesTemplates (樣板)(樣板)

Page 2: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

14.1 Introduction14.1 Introduction是考慮以下程式問題:

◦ 請撰寫一個函式將一個整數陣列中的每個元素依序印出。

◦ 如果現在我們也想把字元陣列、浮點數陣列、字串陣列的元素印出的話,跟怎麼作? 必須另外為特定的型態來撰寫此型別專屬的副函式! 樣板( template )的作用即用來解決這樣的問題。

void printArray(const int a[], const int count) { for (int i=0; i<count; i++) cout << a[i] << “ “; cout << endl; }

Page 3: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

14.1 Introduction14.1 IntroductionFunction templates and class

templates◦Programmers are enable to specify

an entire range of related functions and related classes Function-template specializations and

class-template specializations can be generated, respectively.

◦Generic programming

Page 4: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

Software Engineering Observation Software Engineering Observation 14.114.1Most C++ compilers require the

complete definition of a template to appear in the client source-code file that uses the template.

For this reason and for reusability, templates are often defined in header files, which are then #included into the appropriate client source-code files. ◦ For class templates, this means that the

member functions are also defined in the header file.

Page 5: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

14.2 Function Templates14.2 Function TemplatesFunction Templates

◦Used to produce overloaded functions that perform identical operations on different types of data First, programmer writes a single

function-template definition. Compiler generates separate object-code

functions (function-template specializations) based on argument types in calls to the function template

Page 6: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

14.2 Function Templates 14.2 Function Templates Function-template definitions

◦Starting with a template header Keyword template List of template parameters

Enclosed in angle brackets (< and >) Each template parameter is preceded by keyword class or keyword typename (both are interchangeable)

Used to specify types of arguments to, local variables in and return type of the function template

Examples template< typename T > template< class ElementType > template< typename BorderType, typename Filltype >

Page 7: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

Common Programming Error Common Programming Error 14.114.1

Not placing keyword class or keyword typename before each type template parameter of a function template is a syntax error.

Page 8: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

fig14_01.cpp (1 of 2)

1 // Fig. 14.1: fig14_01.cpp

2 // Using template functions.

3 #include <iostream>

4 using std::cout;

5 using std::endl;

6

7 // function template printArray definition

8 template< typename T >

9 void printArray( const T *array, int count )

10 {

11 for ( int i = 0; i < count; i++ )

12 cout << array[ i ] << " ";

13

14 cout << endl;

15 } // end function template printArray

16

17 int main()

18 {

19 const int ACOUNT = 5; // size of array a

20 const int BCOUNT = 7; // size of array b

21 const int CCOUNT = 6; // size of array c

22

23 int a[ ACOUNT ] = { 1, 2, 3, 4, 5 };

24 double b[ BCOUNT ] = { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7 };

25 char c[ CCOUNT ] = "HELLO"; // 6th position for null

26

27 cout << "Array a contains:" << endl;

Type template parameter T specified in template header

注意:樣板的定義由template <…> 開始,角刮號中一定至少要定義一種型

態或類別

Page 9: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

fig14_01.cpp (2 of 2)

28

29 // call integer function-template specialization

30 printArray( a, ACOUNT );

31

32 cout << "Array b contains:" << endl;

33

34 // call double function-template specialization

35 printArray( b, BCOUNT );

36

37 cout << "Array c contains:" << endl;

38

39 // call character function-template specialization

40 printArray( c, CCOUNT );

41 return 0;

42 } // end main Array a contains: 1 2 3 4 5 Array b contains: 1.1 2.2 3.3 4.4 5.5 6.6 7.7 Array c contains: H E L L O

Creates a function-template specialization of printArray where int replaces T

Creates a function-template specialization of printArray where double replaces T

Creates a function-template specialization of printArray where char replaces T

Page 10: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

Common Programming Error Common Programming Error 14.214.2If a template is invoked with a user-

defined type, and if that template uses operators (e.g., ==, +, <=) with objects of that class, those operators must be overloaded.

Forgetting to overload such operators causes compilation errors.

Page 11: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

Indicate Any ErrorIndicate Any Error #include <iostream> using namespace std; class Test { public: Test(int s=0) { a = s; } private: int a; } template <typename T> void printArray(const T *a, const int count) { for (int i=0; i<count; i++) cout << a[i] << endl; } void main () { Test b[4]; printArray(b, 4); }

Error:

How to fix?

Page 12: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

Performance Tip 14.1Performance Tip 14.1Remember that multiple function-

template specializations are instantiated in a program (at compile time), despite the fact that the template is written only once. ◦ For the example of fig14_01.cpp, three

specialized functions are generated and compiled:printArray(const int *, const int);printArray(const double *, const int);printArray(const char *, const int);

Page 13: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

14.4 Class Templates14.4 Class TemplatesClass templates (or parameterized

types)◦Class-template definitions start with a

header such as template< typename T >

◦Additional type parameters can be specified using a comma-separated list. For example template< typename T1, typename T2 >

Page 14: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

14.4 Class Templates14.4 Class Templates使用類別樣板( class template )的時機

:◦ 樣板的寫法並非適用於實作所有的類別。

如果類別成員函式的運算大多與成員變數的存取有關,或類別過於複雜,較不適合採用樣板來實作。

如果類別的功用主要作為一種資料結構,單純作為資料的「容器」,則比較適合以樣板來實作。 例如,堆疊、佇列、鏈結串列等。

本節將以「堆疊」( Stack )來說明類別樣板的實作語法。

Page 15: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

An Introduction to StackAn Introduction to StackA kind of data structure Last-In-First-Out (LIFO)

Push (A)

Push (B)

Push (C)

Push (D)

Push (E)

Pop ()

Which one is popped by the function Pop()?

A

B

C

D

E

Add a new item on the top of stack.

Get the item the item at the top of stack and remove it from the stack. top

0

1

2

3

4

5

Page 16: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

Examples of StackExamples of Stack

0 1 2 3 4

0

1

2

3

4(0, 0)(0, 1)(1, 1)(1, 0)(2, 0)(2, 1)(3, 1)(3, 0)(4, 0)(4, 1)

(3, 2)

Page 17: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

An Implementation of An Implementation of StackStackImplement Stack using an array.

◦ Assume integer elements are considered. class Stack { public: Stack (int = 10); //Default constructor ~Stack(); bool push (int); //Push an integer into the stack; return true if successful bool pop (int &); //Pop an integer from the stack; return true if successful bool isEmpty() const; //Return true if the array is empty bool isFull() const; //Return true if the array is full private: int size; //array size int top; //initialized to -1; always maintain the next index to pop int *stackPtr; };

Page 18: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

Stack (int s) : size( (s > 0)? s : 10 ), top(-1) { stackPtr = new int[size]; } ~Stack() { delete [] stackPtr; } bool Stack::push (int pushValue) { if (!isFull()) { stackPtr[++top] = pushValue; return true; } return false; } bool Stack:: pop (int &popValue) { if (!isEmpty()) { popValue = stackPtr[top--]; return true; } return false; }bool Stack::isFull () const{ return (top == size); }

bool Stack::isEmpty () const { return (top == -1); }

Page 19: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

An Implementation of StackAn Implementation of StackNow consider object elements.

class Stack { public: Stack (int = 10); //Default constructor ~Stack(); bool push (const Point &); //Push a Point object into the stack; return true if successful bool pop (Point &); //Pop a Point object from the stack; return true if successful bool isEmpty() const; //Return true if the array is empty bool isFull() const; //Return true if the array is full private: int size; //array size int top; //initialized to -1; always maintain the next index to pop Point *stackPtr; };

class Point { public: Point(int a=0, int b=0) : x(a), y(b) { } private: int x, y; };

Page 20: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

Stack (int s) : size( (s > 0)? s : 10 ), top(-1) { stackPtr = new Point[size]; } ~Stack() { delete [] stackPtr; } bool Stack::push (int pushValue) { if (!isFull()) { stackPtr[++top] = pushValue; return true; } return false; } bool pop (int &popValue) { if (!isEmpty()) { popValue = stackPtr[top--]; return true; } return false; }bool Stack::isFull (){ return (top == size); }

bool Stack::isEmpty () { return (top == -1); }

請注意,陣列中如果每個元素都是物件,在呼叫每個物件的建構子時不會給引數,因此請記得為你的資料類別(如本例的 Poin

t )提供預設建構子。

請注意此兩行敘述。在這兩行中,涉及物件的指定。因為最好為資料類別(如本例的 Point )提供拷貝建構子與賦值運算子多載函式。

Page 21: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

ObservationsObservationsStack 的操作在於物件的建立與指定,其運作與資

料的內容無關。◦ Stack 不需要是 Point 類別的夥伴類別;因為 Stack 的運

作沒有讀取其成員變數的必要。Stack 扮演「容器」的角色;代表其當中存放的內

容(型態)隨時會改變。◦ 內容一改變,就必須重新實作新的 Stack 類別?!◦ 解決方法:利用樣板( template )

Page 22: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

Stack.h (1 of 3)

1 // Fig. 14.2: Stack.h

2 // Stack class template.

3 #ifndef STACK_H

4 #define STACK_H

5

6 template< typename T >

7 class Stack

8 {

9 public:

10 Stack( int = 10 ); // default constructor (Stack size 10)

11

12 // destructor

13 ~Stack()

14 {

15 delete [] stackPtr; // deallocate internal space for Stack

16 } // end ~Stack destructor

17

18 bool push( const T& ); // push an element onto the Stack

19 bool pop( T& ); // pop an element off the Stack

20

21 // determine whether Stack is empty

22 bool isEmpty() const

23 {

24 return top == -1;

25 } // end function isEmpty

這一行寫在類別的宣告前面,代表要產生一個 class template (類別樣板),角刮號中由 class 或 typename 接續一個標幟名 T ,稱為參數型態;用來代表使用者可自行定義的型態

在此類別樣板的成員宣告中,接著即以型別參數 T 來指定其內容的型別。

Page 23: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

Stack.h (2 of 3)

26

27 // determine whether Stack is full

28 bool isFull() const

29 {

30 return top == size - 1;

31 } // end function isFull

32

33 private:

34 int size; // # of elements in the Stack

35 int top; // location of the top element (-1 means empty)

36 T *stackPtr; // pointer to internal representation of the Stack

37 }; // end class template Stack

38

39 // constructor template

40 template< typename T >

41 Stack< T >::Stack( int s )

42 : size( s > 0 ? s : 10 ), // validate size

43 top( -1 ), // Stack initially empty

44 stackPtr( new T[ size ] ) // allocate memory for elements

45 {

46 // empty body

47 } // end Stack constructor template

資料成員 stackPtr 是一個指標,指向一個 T 的陣列

如果將成員函式提到類別宣告外部來實作,則每個函式都在

跟在一個樣板標頭的後面。

Page 24: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

Stack.h (3 of 3)

48

49 // push element onto Stack;

50 // if successful, return true; otherwise, return false

51 template< typename T >

52 bool Stack< T >::push( const T &pushValue )

53 {

54 if ( !isFull() )

55 {

56 stackPtr[ ++top ] = pushValue; // place item on Stack

57 return true; // push successful

58 } // end if

59

60 return false; // push unsuccessful

61 } // end function template push

62

63 // pop element off Stack;

64 // if successful, return true; otherwise, return false

65 template< typename T >

66 bool Stack< T >::pop( T &popValue )

67 {

68 if ( !isEmpty() )

69 {

70 popValue = stackPtr[ top-- ]; // remove item from Stack

71 return true; // pop successful

72 } // end if

73

74 return false; // pop unsuccessful

75 } // end function template pop

76

77 #endif

Page 25: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

Note Note ★ ★ ★ ★ ★★ ★ ★ ★ ★Software Engineering Observation

14.1◦ Most C++ compilers require the complete

definition of a template to appear in the client source-code file that uses the template.

◦ For class templates, this means that the member functions are also defined in the header file.

◦ 請注意!樣板的運作模式是,是由編譯器根據樣板的定義,以及使用者所指定的型別,先自動產生出對應的程式碼後再行編譯。編譯的過程與一般的類別不同(個別編譯後進行連結),因此大部分的 C++ 編譯器會要求使用樣板的程式檔要包含完整的樣板定義,所以我們會把樣板的完整定義(包含成員函式的實作)一律寫在 .h檔中,這和一般我們設計類別時,要求宣告和實作要分開的情況不同。

Page 26: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

fig14_03.cpp (1 of 3)

1 // Fig. 14.3: fig14_03.cpp

2 // Stack class template test program.

3 #include <iostream>

4 using std::cout;

5 using std::endl;

6

7 #include "Stack.h" // Stack class template definition

8

9 int main()

10 {

11 Stack< double > doubleStack( 5 ); // size 5

12 double doubleValue = 1.1;

13

14 cout << "Pushing elements onto doubleStack\n";

15

16 // push 5 doubles onto doubleStack

17 while ( doubleStack.push( doubleValue ) )

18 {

19 cout << doubleValue << ' ';

20 doubleValue += 1.1;

21 } // end while

22

23 cout << "\nStack is full. Cannot push " << doubleValue

24 << "\n\nPopping elements from doubleStack\n";

25

26 // pop elements from doubleStack

27 while ( doubleStack.pop( doubleValue ) )

28 cout << doubleValue << ' ';

樣板類別定義的所有內容在此標頭檔中

產生特殊化樣板類別( class-template specialization ), Stack<double> 。編譯器會將型態 double 與參數型態 T 連結

Page 27: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

fig14_03.cpp (2 of 3)

29

30 cout << "\nStack is empty. Cannot pop\n";

31

32 Stack< int > intStack; // default size 10

33 int intValue = 1;

34 cout << "\nPushing elements onto intStack\n";

35

36 // push 10 integers onto intStack

37 while ( intStack.push( intValue ) )

38 {

39 cout << intValue << ' ';

40 intValue++;

41 } // end while

42

43 cout << "\nStack is full. Cannot push " << intValue

44 << "\n\nPopping elements from intStack\n";

45

46 // pop elements from intStack

47 while ( intStack.pop( intValue ) )

48 cout << intValue << ' ';

49

50 cout << "\nStack is empty. Cannot pop" << endl;

51 return 0;

52 } // end main

產生特殊化樣板類別( class-template specialization ), Stack<int> 。編譯器會將型態 int 與參數型態T 連結

Page 28: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

fig14_03.cpp (3 of 3)

Pushing elements onto doubleStack 1.1 2.2 3.3 4.4 5.5 Stack is full. Cannot push 6.6 Popping elements from doubleStack 5.5 4.4 3.3 2.2 1.1 Stack is empty. Cannot pop Pushing elements onto intStack 1 2 3 4 5 6 7 8 9 10 Stack is full. Cannot push 11 Popping elements from intStack 10 9 8 7 6 5 4 3 2 1 Stack is empty. Cannot pop

註:在本例中,編譯器實際上將套用型別參數,分別產生兩個 Stack的副本用來處理 double 與 int 的元素資料,就效能來看,其和使用

者自己把 Stack 重寫兩次的結果是一樣的。不過,使用樣板的好處主要是在增加程式碼的可再利用率,避免程式碼的重複撰寫。

Page 29: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

fig14_04.cpp (1 of 3)

1 // Fig. 14.4: fig14_04.cpp

2 // Stack class template test program. Function main uses a

3 // function template to manipulate objects of type Stack< T >.

4 #include <iostream>

5 using std::cout;

6 using std::endl;

7

8 #include <string>

9 using std::string;

10

11 #include "Stack.h" // Stack class template definition

12

13 // function template to manipulate Stack< T >

14 template< typename T >

15 void testStack(

16 Stack< T > &theStack, // reference to Stack< T >

17 T value, // initial value to push

18 T increment, // increment for subsequent values

19 const string stackName ) // name of the Stack< T > object

20 {

21 cout << "\nPushing elements onto " << stackName << '\n';

22

23 // push element onto Stack

24 while ( theStack.push( value ) )

25 {

26 cout << value << ' ';

27 value += increment;

28 } // end while

代表使用參數型態 T ,用來代表 Stack<T> 中的儲存資料型別

注意「 += 」運算子的使用;如果 T 是一個自訂類別的話,則如果要在其物件進行「 += 」的運算,代表此類別必須要_______________________

Page 30: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

fig14_04.cpp (2 of 3)

29

30 cout << "\nStack is full. Cannot push " << value

31 << "\n\nPopping elements from " << stackName << '\n';

32

33 // pop elements from Stack

34 while ( theStack.pop( value ) )

35 cout << value << ' ';

36

37 cout << "\nStack is empty. Cannot pop" << endl;

38 } // end function template testStack

39

40 int main()

41 {

42 Stack< double > doubleStack( 5 ); // size 5

43 Stack< int > intStack; // default size 10

44

45 testStack( doubleStack, 1.1, 1.1, "doubleStack" );

46 testStack( intStack, 1, 1, "intStack" );

47

48 return 0;

49 } // end main

Page 31: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

14.5 Nontype Parameters and Default 14.5 Nontype Parameters and Default Types for Class TemplatesTypes for Class TemplatesNontype template parameters

◦ Can have default arguments◦ Are treated as const◦ Example

Template header:template< typename T, int elements >

In the constructor, we can use nontype paramemter stackPtr = new T[ elements ];

Declaration:Stack< double, 100 > salesFigures;

Page 32: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

14.5 Nontype Parameters and Default 14.5 Nontype Parameters and Default Types for Class TemplatesTypes for Class TemplatesType parameters can have default

arguments too◦ Example

Template header:template< typename T = string >

Declaration:Stack<> jobDescriptions;

Page 33: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

ExerciseExerciseUse the concept of template to implement

Queue.What is a queue?

◦ First-In-First-Out (FIFO)

Push (A)

Push (B)

Push (C)

Push (D)

Pop (E)

Pop ()

Which one is deleted by the function Pop()?

A

B

C

D

EAdd a new item on the rear of queue.

Get the item at the front of queue and remove it from the queue.

rearfront

Page 34: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

An Implementation of An Implementation of QueueQueueAssume integer elements are

considered. class Queue { public: Queue (int = 10); //Default constructor ~ Queue(); bool push (int); //Push an integer into the queue; return true if successful bool pop (int &); //Pop an integer from the queue; return true if successful bool isEmpty() const; //Return true if the array is empty bool isFull() const; //Return true if the array is full private: int size; //array size int front, rear; //initialized to 0 int *queuePtr; };

Page 35: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

Implementing Queue Using Implementing Queue Using ArrayArray

Suppose the length of array is n. ◦ This approach runs into a problem when rear

equals to n-1.◦ Shifting all elements to the left? Time-consuming.

A A B A B C

rear rear rear

B C

rearfront

B C D

rearfront

front

Page 36: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

Circular QueueCircular Queue

A

B C

D

0 1 2 3 4 5 6 7

A B C D

0

1

2 3

4

5

67

rear

front

rear

rear rear

front

front

Push (A)

Push (B)

Push (C)

Push (D)

Pop ()

Pop ()

Pop ()

Push (E)

Push (F)

Push (G)

Push (H)

Push (I)

rear

rear

frontfront

E

FG

H

I

E

rear

F

rear

G

rear

H I

Page 37: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

0

1

2 3

4

5

67

rear

front

0

1

2 3

4

5

67

front

rear

A

B C

D

E

FGrear

H

How do know whether the queue is empty or full?

Page 38: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

An Implementation of An Implementation of QueueQueueAssume integer elements are

considered. class Queue { public: Queue (int = 10); //Default constructor ~ Queue(); bool push (int); //Push an integer into the queue; return true if successful bool pop (int &); //Pop an integer from the queue; return true if successful bool isEmpty() const; //Return true if the array is empty bool isFull() const; //Return true if the array is full private: int size; //array size int front, rear; //initialized to -1; always maintain the next index to pop int *queuePtr; };

Queue (int s) : size( (s > 0)? s : 10 ), front(0), rear(0) { queuePtr = new int[size]; } ~Queue() { delete [] queuePtr; } bool Queue::push (int pushValue) { if (!isFull()) { rear = (rear+1) % size; queuePtr[rear] = pushValue; return true; } return false; } bool Queue:: pop (int &popValue) { if (!isEmpty()) { front = (front+1) % size; popValue = queuePtr[front]; return true; } return false; }bool Queue ::isFull () const{ return ((rear+1) % size == front); }

bool Queue ::isEmpty () const { return (rear == front); }

Page 39: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

Implementing Queue Using Implementing Queue Using TemplateTemplate #ifndef QUEUE_H #define QUEUE_H

template <typename T> class Queue { public: Queue(int = 10); ~Queue(); bool push( const T & ); bool pop( T & ); bool isFull() const; bool isEmpty() const; private: int size; int front, rear; T *queuePtr; } ;

1.

2.

3.

4.

Page 40: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

Implementing Queue Using Implementing Queue Using TemplateTemplate

Assume integer elements are considered. class Queue

{ public: Queue (int = 10); //Default constructor ~ Queue(); bool push (int); //Push an integer into the queue; return true if successful bool pop (int &); //Pop an integer from the queue; return true if successful bool isEmpty() const; //Return true if the array is empty bool isFull() const; //Return true if the array is full private: int size; //array size int front, rear; //initialized to -1; always maintain the next index to pop int *queuePtr; };

template <typename T> Queue<T>:: Queue (int s) : size( (s > 0)? s : 10 ), front(0), rear(0) { queuePtr = new T[size]; }

template <typename T> Queue<T> :: ~Queue() { delete [] queuePtr; }

template <typename T> bool Queue:: push ( const T &pushValue ) { if (!isFull()) { rear = (rear+1) % size; queuePtr[rear] = pushValue; return true; } return false; }

5.

6.

7.

8.

9.

10.

11. 12.

Page 41: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

Implementing Queue Using Implementing Queue Using TemplateTemplate

class Queue { public: Queue (int = 10); //Default constructor ~ Queue(); bool push (int); //Push an integer into the queue; return true if successful bool pop (int &); //Pop an integer from the queue; return true if successful bool isEmpty() const; //Return true if the array is empty bool isFull() const; //Return true if the array is full private: int size; //array size int front, rear; //initialized to -1; always maintain the next index to pop int *queuePtr; };

template <typename T> bool Queue<T> :: pop ( T &popValue ) { if (!isEmpty()) { front = (front+1) % size; popValue = queuePtr[front]; return true; } return false; }

template <typename T> bool Queue<T>:: isFull () const { return ((rear+1) % size == front); } template <typename T> bool Queue<T>:: isEmpty () const { return (rear == front); } #endif

13.

17.

16.

14.

19.

18.

15.

Page 42: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

7.11 Introduction to C++ Standard 7.11 Introduction to C++ Standard Library Class Template Library Class Template vectorvectorC-style pointer-based arrays

◦Have great potential for errors and several shortcomings C++ does not check whether subscripts

fall outside the range of the array Two arrays cannot be meaningfully

compared with equality or relational operators

One array cannot be assigned to another using the assignment operators

Page 43: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

7.11 Introduction to C++ Standard 7.11 Introduction to C++ Standard Library Class Template Library Class Template vectorvector

Class template vector◦ Available to anyone building applications with C++◦ Can be defined to store any data type

Specified between angle brackets in vector< type >

All elements in a vector are set to 0 by default◦ Member function size obtains size of array

Number of elements as a value of type size_t◦ vector objects can be compared using equality and

relational operators.◦ Assignment operator can be used for assigning vectors.

◦ Individual elements can be accessed with square brackets.

Page 44: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

7.11 Introduction to C++ Standard 7.11 Introduction to C++ Standard Library Class Template Library Class Template vectorvectorvector member function at

◦Provides access to individual elements◦Performs bounds checking

Throws an exception when specified index is invalid

Accessing with square brackets does not perform bounds checking

Page 45: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

1 // Fig. 7.26: fig07_26.cpp

2 // Demonstrating C++ Standard Library class template vector.

3 #include <iostream>

4 using std::cout;

5 using std::cin;

6 using std::endl;

7

8 #include <iomanip>

9 using std::setw;

10

11 #include <vector>

12 using std::vector;

13

14 void outputVector( const vector< int > & ); // display the vector

15 void inputVector( vector< int > & ); // input values into the vector

16

17 int main()

18 {

19 vector< int > integers1( 7 ); // 7-element vector< int >

20 vector< int > integers2( 10 ); // 10-element vector< int >

21

22 // print integers1 size and contents

23 cout << "Size of vector integers1 is " << integers1.size()

24 << "\nvector after initialization:" << endl;

25 outputVector( integers1 );

26

27 // print integers2 size and contents

28 cout << "\nSize of vector integers2 is " << integers2.size()

29 << "\nvector after initialization:" << endl;

30 outputVector( integers2 );

fig07_26.cpp (1 of 6)

類別樣板 vector 將儲存 int 元素

vector<int> 為特殊化類別樣板,儲存資料型別已經明確定

vector 類別樣板內含成員變數 size ,用來記錄

當中的元素個數

Page 46: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

31

32 // input and print integers1 and integers2

33 cout << "\nEnter 17 integers:" << endl;

34 inputVector( integers1 );

35 inputVector( integers2 );

36

37 cout << "\nAfter input, the vectors contain:\n"

38 << "integers1:" << endl;

39 outputVector( integers1 );

40 cout << "integers2:" << endl;

41 outputVector( integers2 );

42

43 // use inequality (!=) operator with vector objects

44 cout << "\nEvaluating: integers1 != integers2" << endl;

45

46 if ( integers1 != integers2 )

47 cout << "integers1 and integers2 are not equal" << endl;

48

49 // create vector integers3 using integers1 as an

50 // initializer; print size and contents

51 vector< int > integers3( integers1 ); // copy constructor

52

53 cout << "\nSize of vector integers3 is " << integers3.size()

54 << "\nvector after initialization:" << endl;

55 outputVector( integers3 );

56

57 // use overloaded assignment (=) operator

58 cout << "\nAssigning integers2 to integers1:" << endl;

59 integers1 = integers2; // integers1 is larger than integers2

fig07_26.cpp (2 of 6)

你可以比較兩個 vector 物件是否相等。因為該類別 _______了「 != 」

運算子

你也可以從一個 vector 物件建立它的副本,或作兩個物件的指定。因為該類別提供了 _______ 以及 _________

Page 47: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

60

61 cout << "integers1:" << endl;

62 outputVector( integers1 );

63 cout << "integers2:" << endl;

64 outputVector( integers2 );

65

66 // use equality (==) operator with vector objects

67 cout << "\nEvaluating: integers1 == integers2" << endl;

68

69 if ( integers1 == integers2 )

70 cout << "integers1 and integers2 are equal" << endl;

71

72 // use square brackets to create rvalue

73 cout << "\nintegers1[5] is " << integers1[ 5 ];

74

75 // use square brackets to create lvalue

76 cout << "\n\nAssigning 1000 to integers1[5]" << endl;

77 integers1[ 5 ] = 1000;

78 cout << "integers1:" << endl;

79 outputVector( integers1 );

80

81 // attempt to use out-of-range subscript

82 cout << "\nAttempt to assign 1000 to integers1.at( 15 )" << endl;

83 integers1.at( 15 ) = 1000; // ERROR: out of range

84 return 0;

85 } // end main

fig07_26.cpp (3 of 6)

vector 多載註標運算子,用來存取某一個元素的內容;然而註標運算子的多載函式並未提供範圍的檢查

函式 at() 也同樣可以用來存取某一個元素的內容;然而此函式提供範圍的檢查

Page 48: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

86

87 // output vector contents

88 void outputVector( const vector< int > &array )

89 {

90 size_t i; // declare control variable

91

92 for ( i = 0; i < array.size(); i++ )

93 {

94 cout << setw( 12 ) << array[ i ];

95

96 if ( ( i + 1 ) % 4 == 0 ) // 4 numbers per row of output

97 cout << endl;

98 } // end for

99

100 if ( i % 4 != 0 )

101 cout << endl;

102 } // end function outputVector

103

104 // input vector contents

105 void inputVector( vector< int > &array )

106 {

107 for ( size_t i = 0; i < array.size(); i++ )

108 cin >> array[ i ];

109 } // end function inputVector

fig07_26.cpp (4 of 6)

Page 49: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

fig07_26.cpp (5 of 6)

Size of vector integers1 is 7 vector after initialization: 0 0 0 0 0 0 0 Size of vector integers2 is 10 vector after initialization: 0 0 0 0 0 0 0 0 0 0 Enter 17 integers:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 After input, the vectors contain: integers1: 1 2 3 4 5 6 7 integers2: 8 9 10 11 12 13 14 15 16 17 Evaluating: integers1 != integers2 integers1 and integers2 are not equal Size of vector integers3 is 7 vector after initialization: 1 2 3 4 5 6 7 (continued at top of next slide )

Execution ResultExecution Result

Page 50: Chapter 14 Templates (樣板) Chapter 14 Templates (樣板)

fig07_26.cpp (6 of 6) ( continued from bottom of previous slide) Assigning integers2 to integers1: integers1: 8 9 10 11 12 13 14 15 16 17 integers2: 8 9 10 11 12 13 14 15 16 17 Evaluating: integers1 == integers2 integers1 and integers2 are equal integers1[5] is 13 Assigning 1000 to integers1[5] integers1: 8 9 10 11 12 1000 14 15 16 17 Attempt to assign 1000 to integers1.at( 15 ) abnormal program termination

Execution ResultExecution Result

超出索引範圍, at() 將強制終止程式。