CÁC HÀM TEMPLATE

Một phần của tài liệu Tài liệu Giáo trình OOP Đà Nẵng docx (Trang 159 - 161)

Các hàm đa năng hóa bình thường được sử dụng để thực hiện các thao tác tương tự trên các kiểu khác nhau của dữ liệu. Nếu các thao tác đồng nhất cho mỗi kiểu, điều này có thể thực hiện mạch lạc và thuận tiện hơn sử dụng các hàm template. Lập trình viên viết định nghĩa hàm template đơn giản. Dựa vào các kiểu tham số cung cấp trong lời gọi hàm này, trình biên dịch tựđộng phát sinh các hàm mã đối tượng riêng biệt để xử

lý mỗi kiểu của lời gọi thích hợp. Trong C, điều này có thểđược thực hiện bằng cách sử dụng các macro tạo với tiền xử lý #define. Tuy nhiên, các macro biểu thị khả năng đối với các hiệu ứng lề nghiêm trọng và không cho phép trình biên dịch thực hiện việc kiểm tra kiểu. Các hàm template cung cấp một giải pháp mạch lạc giống như các macro, nhưng cho phép kiểm tra kiểu đầy đủ. Chẳng hạn, chúng ta muốn viết hàm lấy trị

tuyệt đối của một số, chúng ta có thể viết nhiều dạng khác nhau như sau:

int MyAbs(int X) { return X>=0?X:-X; } long MyAbs(long X) { return X>=0?X:-X; } double MyAbs(double X) { return X>=0?X:-X; }

Tuy nhiên với các hàm này chúng ta vẫn chưa có giải pháp tốt, mang tính tổng quát nhất như hàm có tham số kiểu int nhưng giá trị trả về là double và ngược lại.

Tất cả các hàm template định nghĩa bắt đầu với từ khóa template theo sau một danh sách các tham số

hình thức với hàm template vây quanh trong các ngoặc nhọn (<>); Mỗi tham số hình thức phải được đặt trước bởi từ khóa class như:

template <class T>

hoặc template <class T1, class T2,…>

Các tham số hình thức của một định nghĩa template được sử dụng để mô tả các kiểu của các tham số cho hàm, để mô tả kiểu trả về của hàm, và để khai báo các biến bên trong hàm. Phần định nghĩa hàm theo sau và

được định nghĩa giống như bất kỳ hàm nào. Chú ý từ khóa class sử dụng để mô tả các kiểu tham số của hàm template thực sự nghĩa là "kiểu có sẵn và kiểu người dùng định nghĩa bất kỳ".

160

Khi đó, hàm trị tuyệt đối ở trên viết theo hàm template:

template <class T> T MyAbs(T x) {

return (x>=0)?x:-x; }

Hàm template MyAbs() khai báo một tham số hình thức T cho kiểu của một số. T được tham khảo như

một tham số kiểu. Khi trình biên dịch phát hiện ra một lời gọi hàm MyAbs() trong chương trình, kiểu của tham số thứ nhất của hàm MyAbs() được thay thế cho T thông qua định nghĩa template, và C++ tạo một hàm template đầy đủđể trả về trị tuyệt đối của một số của kiểu dữ liệu đã cho. Sau đó, hàm mới tạo được biên dịch. Chẳng hạn:

cout<<MyAbs(-2)<<endl; cout<<MyAbs(3.5)<<endl;

Trong lần gọi thứ nhất, hàm MyAbs() có tham số thực là int nên trình biên dịch tạo ra hàm int

MyAbs(int) theo dạng của hàm template, lần thứ hai sẽ tạo ra hàm float MyAbs(float).

Mỗi tham số hình thức trong một định nghĩa hàm template phải xuất hiện trong danh sách tham số của hàm tối thiểu một lần. Tên của tham số hình thức chỉ có thể sử dụng một lần trong danh sách tham số của phần đầu template. Ví dụ 9.1: Sử dụng hàm template để in các giá trị của một mảng có kiểu bất kỳ. 1: //Chương trình 9.1 2: #include <iostream.h> 3: 4: template<class T>

5: void PrintArray(T *Array, const int Count) 6: {

7: for (int I = 0; I < Count; I++) 8: cout << Array[I] << " "; 9: 10: cout << endl; 11: } 12: 13: int main() 14: {

15: const int Count1 = 5, Count2 = 7, Count3 = 6; 16: int A1[Count1] = {1, 2, 3, 4, 5};

17: float A2[Count2] = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7}; 18: char A3[Count3] = "HELLO";

19: cout << "Array A1 contains:" << endl;

20: PrintArray(A1, Count1); //Hàm template kiểu int

21: cout << "Array A2 contains:" << endl;

22: PrintArray(A2, Count2); //Hàm template kiểu float

23: cout << "Array A3 contains:" << endl;

24: PrintArray(A3, Count3); //Hàm template kiểu char

25: return 0; 26: }

161

Hình 9.1: Kết quả của ví dụ 9.1 Ví dụ 9.2: Hàm template có thể có nhiều tham số.

1: //Chương trình 9.2 2: #include <iostream.h> 3: 4: template<class T> 5: T Max(T a, T b) 6: { 7: return (a>b)?a:b; 8: } 9: 10: int main() 11: { 12: float A,B;

13: cout<<"Enter first number:"; 14: cin>>A;

15: cout<<"Enter second number:"; 16: cin>>B; 17: cout<<"Maximum:"<<Max(A,B); 18: return 0; 19: } Chúng ta chạy ví dụ 9.2, kết quảở hình 9.2 Hình 9.2: Kết quả của ví dụ 9.2

Một hàm template có thểđược đa năng hóa theo vài cách. Chúng ta có thể cung cấp các hàm template khác mà mô tả cùng tên hàm nhưng các tham số hàm khác nhau. Một hàm template cũng có thể được đa năng hóa bởi cung cấp hàm non-template với cùng tên hàm nhưng các tham số hàm khác nhau. Trình biên dịch thực hiện một xử lý so sánh để xác định hàm gọi khi một hàm được gọi. Đầu tiên trình biên dịch cố

gắng tìm và sử dụng một đối sánh chính xác mà các tên hàm và các kiểu tham sốđối sánh chính xác. Nếu

điều này thất bại, trình biên dịch kiểm tra nếu một hàm template đã có mà có thể phát sinh một hàm template với một đối sánh chính xác của tên hàm và các kiểu tham số. Nếu một hàm template như thếđược tìm thấy, trình biên dịch phát sinh và sử dụng hàm template thích hợp. Chú ý xử lý đối sánh này với các template đòi yêu các đối sánh chính xác trên tất cả kiểu tham số-không có các chuyển đổi tựđộng được áp dụng.

Một phần của tài liệu Tài liệu Giáo trình OOP Đà Nẵng docx (Trang 159 - 161)

Tải bản đầy đủ (PDF)

(165 trang)