Bên cạnh hàm template, ngôn ngữ C++ còn trang bị thêm lớp template, lớp này cũng mang đầy đủ ý tưởng của hàm template. Các lớp template được gọi là các kiểu có tham số (parameterized types) bởi vì chúng đòi hỏi một hoặc nhiều tham số để mô tả làm thế nào tùy chỉnh một lớp template chung để tạo thành một lớp template cụ thể.
162
Chúng ta cài đặt một lớp Stack, thông thường chúng ta phải định nghĩa trước một kiểu dữ liệu cho từng phần tử của stack. Nhưng điều này chỉ mang lại sự trong sáng cho một chương trình và không giải quyết
được vấn đề tổng quát. Do đó chúng ta định nghĩa lớp template Stack. Ví dụ 9.3: File TSTACK.H: 1: //TSTACK.H 2: //Lớp template Stack 3: #ifndef TSTACK_H 4: #define TSTACK_H 5: 6: #include <iostream.h> 7: 8: template<class T> 9: class Stack 10: { 11: private:
12: int Size; //Kích thước stack
13: int Top; 14: T *StackPtr; 15: public: 16: Stack(int = 10); 17: ~Stack() 18: { 19: delete [] StackPtr; 20: }
21: int Push(const T&); 22: int Pop(T&);
23: int IsEmpty() const 24: {
25: return Top == -1; 26: }
27: int IsFull() const 28: {
29: return Top == Size - 1; 30: } 31: }; 32: 33: template<class T> 34: Stack<T>::Stack(int S) 35: { 36: Size = (S > 0 && S < 1000) ? S : 10; 37: Top = -1;
38: StackPtr = new T[Size]; 39: }
40:
41: template<class T>
42: int Stack<T>::Push(const T &Item) 43: { 44: if (!IsFull()) 45: { 46: StackPtr[++Top] = Item; 47: return 1; 48: } 49: return 0; 50: } 51:
163 52: template<class T>
53: int Stack<T>::Pop(T &PopValue) 54: { 55: if (!IsEmpty()) 56: { 57: PopValue = StackPtr[Top--]; 58: return 1; 59: } 60: return 0; 61: } 62: 63: #endif File CT9_3.CPP: 1: //CT9_3.CPP 2: //Chương trình 9.3 3: #include "tstack.h" 4: 5: int main() 6: { 7: Stack<float> FloatStack(5); 8: float F = 1.1;
9: cout << "Pushing elements onto FloatStack" << endl; 10: while (FloatStack.Push(F))
11: {
12: cout << F << ' '; 13: F += 1.1;
14: }
15:cout << endl << "Stack is full. Cannot push " << F << endl 16: << endl << "Popping elements from FloatStack" << endl; 17: while (FloatStack.Pop(F))
18: cout << F << ' ';
19: cout << endl << "Stack is empty. Cannot pop" << endl; 20: Stack<int> IntStack;
21: int I = 1;
22: cout << endl << "Pushing elements onto IntStack" << endl; 23: while (IntStack.Push(I))
24: {
25: cout << I << ' '; 26: ++I ;
27: }
28:cout << endl << "Stack is full. Cannot push " << I << endl 29: << endl << "Popping elements from IntStack" << endl; 30: while (IntStack.Pop(I))
31: cout << I << ' ';
32: cout << endl << "Stack is empty. Cannot pop" << endl; 33: return 0;
34: }
164
Hình 9.3: Kết quả của ví dụ 9.3 Hàm thành viên định nghĩa bên ngoài lớp template bắt đầu với phần đầu là
template <class T>
Sau đó mỗi định nghĩa tương tự một định nghĩa hàm thường ngoại trừ kiểu phần tử luôn luôn được liệt kê tổng quát như tham số kiểu T. Chẳng hạn:
template<class T>
int Stack<T>::Push(const T &Item) {
………. }
Ngôn ngữ C++ còn cho phép chúng ta tạo ra các lớp template linh động hơn bằng cách cho phép thay
đổi giá trị của các thành viên dữ liệu bên trong lớp. Khi đó lớp có dạng của một hàm với tham số hình thức.
BÀI TẬP
Bài 1: Viết hàm template trả về giá trị trung bình của một mảng, các tham số hình thức của hàm này là tên mảng và kích thước mảng.
Bài 2: Cài đặt hàng đợi template.
Bài 3: Cài đặt lớp template dùng cho cây nhị phân tìm kiếm (BST).
Bài 4: Cài đặt lớp template cho vector để quản lý vector các thành phần có kiểu bất kỳ. Bài 5: Viết hàm template để sắp xếp kiểu dữ liệu bất kỳ.
Bài 6: Trong C++, phép toán new được dùng để cấp phát bộ nhớ, khi không cấp phát được con trỏ có giá trị NULL. Hãy cài đặt lại các lớp Matrix và Vector trong đó có bổ sung thêm thành viên là lớp exception với tên gọi là Memory để kiểm tra việc cấp phát này.
165
TÀI LIỆU THAM KHẢO
[1] Lập trình hướng đối tượng C++ của Nguyễn Thanh Thuỷ [2] Lập trình hướng đối tượng C++ của Trần Văn Lăng [3] C++ Kỹ thuật và Ứng dụng – Scott Robert Ladd [4] Ngôn ngữ lập trình C và C++
[5] Bài tập Lập trình hướng đối tượng - Nguyễn Thanh Thuỷ
[6] Introduction to Object-Oriented Programming Using C++ - Peter Müller [7] ..