Template và điều khiển ngoại lệ

39 253 0
Template và điều khiển ngoại lệ

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

lap trinh huong doi tuong voi c++

Chương 10 Template điều khiển ngoại lệ • Hàm template • Lớp templateĐiều khiển ngoại lệ • Biến tónh • Từ khoá extern asm • Hàm chuyển kiểu • Những khác biệt giữa C C++ Chửụng 10 Template vaứ ủieu khieồn ngoaùi leọ 298 Chương 10 Template điều khiển ngoại lệ 299 I/ Hàm template Hàm template (hàm mẫu) đònh nghiã một dãy tổng quát các tác vụ được dùng cho nhiều kiểu dữ liệu khác nhau . Trong đó, kiểu dữ liệu được dùng sẽ được truyền đến hàm dưới dạng một tham số . Với cơ chế này, một thủ tục có thể được dùng cho nhiều kiểu dữ liệu khác nhau . Trong môn học Cấu trúc dữ liệu thuật toán, nhiều giải thuật giống nhau về mặt luận lý, bất kể nó làm việc với kiểu dữ liệu gì. Ví dụ giải thuật QuickSort là giống nhau, không cần biết nó sẽ áp dụng cho dãy số nguyên hay dãy số thực. Vấn đề là ở chỗ dữ liệu được xử lý khác nhau. Bằng cách tạo ra hàm template, có thể đònh nghiã bản chất của giải thuật độc lập với kiểu dữ liệu mà nó xử lý. Dựa vào hàm template, trình biên dòch sẽ tự động sinh ra mã chương trình để dùng cho một kiểu dữ liệu cụ thể nào đó khi thực thi chương trình. Thực chất là việc tạo ra một hàm template đồng nghiã với việc tạo ra một hàm mà nó có thể tự quá tải lên chính nó . Khai báo hàm template template < class Ttype > ret_type func_name (parameter list) { // body of function } Từ khoá template dùng để tạo ra một dạng mẫu mô tả hoạt động của hàm nhường cho trình biên dòch điền vào một cách chi tiết khi cần. Ttype là tên hình thức cho kiểu dữ liệu được dùng bên trong hàm, nó sẽ được thay thế bởi một kiểu dữ liệu cụ thể khi trình biên dòch sinh ra một phiên bản chi tiết của hàm. Quá trình tạo ra phiên bản chi tiết của hàm được gọi là quá trình sinh hàm. Việc tạo ra bản chi tiết của hàm template được gọi là tạo ra ngay tức khắc (instantiating) một hàm. Nói một cách khác là một hàm sinh ra phiên bản dùng trong chốc lát của hàm template . Chương 10 Template điều khiển ngoại lệ 300 Ví dụ 1.1 Hàm template trao đổi nội dung của hai biến // Function template example. #include <iostream.h> // This is a function template. template <class X > void swapargs (X &a, X &b) { X temp; temp = a; a = b; b = temp; } int main() { int i=10, j=20; float x=10.1, y=23.3; cout << "Original i, j: " << i << ' ' << j << endl; cout << "Original x, y: " << x << ' ' << y << endl; swapargs ( i, j ); // swap integers swapargs ( x, y ); // swap floats cout << "Swapped i, j: " << i << ' ' << j << endl; cout << "Swapped x, y: " << x << ' ' << y << endl; return 0; } template <class X > void swapargs (X &a, X &b) Dòng này thông báo với chương trình hai vấn đề : - Đây là một hàm template. - Đây là điểm bắt đầu của phần đònh nghiã một hàm template. X có ý nghiã là kiểu dữ liệu của các biến cần trao đổi nội dung. Chương 10 Template điều khiển ngoại lệ 301 Hàm swapargs () được gọi hai lần trong hàm main() : một lần để trao đổi nội dung hai biến kiểu số nguyên, lần sau cho hai biến kiểu số thực. Do hàm swapargs () là một hàm template, cho nên trình biên dòch sẽ tự động phát sinh ra hai phiên bản của hàm swapargs () tương ứng với kiểu dữ liệu của đối số thực gởi vào. • Phần khai báo template của một hàm mẫu không bắt buộc phải viết trên cùng một dòng với tên hàm. Ví dụ 1.2 template <class X> void swapargs (X &a, X &b) { X temp; temp = a; a = b; b = temp; } • Chú ý rằng, không thể đặt bất kỳ mệnh đề nào giữa phần khai báo template phần thân hàm. Ví dụ 1.3 // This will not compile. template <class X> int i ; // this is an error void swapargs(X &a, X &b) { X temp; temp = a; a = b; b = temp; } Chương 10 Template điều khiển ngoại lệ 302 • Trong hàm template, có thể sử dụng nhiều kiểu dữ liệu khác nhau bằng cách đưa vào một danh sách các kiểu dữ liệu dùng trong hàm, trong đó tên hình thức của các kiểu được phân cách nhau bằng dấu phẩy. #include <iostream.h> template <class type1 , class type2 > void myfunc( type1 x, type2 y) { cout << x << ' ' << y << endl; } int main() { myfunc(10, "hi"); myfunc(0.23, 10L); return 0; } @ Khi phát sinh hàm, các kiểu hình thức type1 type2 được thay thế hai lần : lần đầu bằng hai kiểu int char*, lần sau là double long . • Hàm template tương tự như hàm được quá tải nhưng nó chòu nhiều hạn chế hơn. Khi quá tải một hàm, các phiên bản có thể mang nhiều tác vụ rất khác nhau, trong khi một hàm template chỉ thực hiện được một công việc duy nhất ở tất cả các phiên bản . Ví dụ không thể thay thế hàm được quá tải sau đây bằng một hàm template bởi vì các hàm quá tải sau đây không cùng thực thi một công việc. void outdata(int i) { cout << i; } Chương 10 Template điều khiển ngoại lệ 303 void outdata(double d) { cout << setprecision(10) << setfill('#'); cout << d; cout << setprecision(6) << setfill(' '); } • Một hàm template có thể tự quá tải khi cần thiết, khi đó cần quá tải nó một cách tường minh. Nếu quá tải một hàm template thì hàm được quá tải sẽ che hàm template đó . // Overriding a template function. #include <iostream.h> template <class X> void swapargs(X &a, X &b) { X temp; temp = a; a = b; b = temp; } // This overrides the generic version of swapargs(). void swapargs(int a, int b) { cout << "this is inside swapargs(int,int)\n"; } int main() { int i=10, j=20; float x=10.1, y=23.3; cout << "Original i, j: " << i << ' ' << j << endl; cout << "Original x, y: " << x << ' ' << y << endl; Chương 10 Template điều khiển ngoại lệ 304 swapargs(i, j) ; // this calls the explicitly overloaded swapargs() swapargs(x, y); // swap floats cout << "Swapped i, j: " << i << ' ' << j << endl; cout << "Swapped x, y: " << x << ' ' << y << endl; return 0; } @ Việc quá tải lên một hàm template, cho phép lập trình viên thay đổi giải thuật của một phiên bản của hàm template để phù hợp với một tình huống đặc biệt . Tuy nhiên, nếu muốn sử dụng những phiên bản hoàn toàn khác nhau của một hàm trong đó có nhiều kiểu dữ liệu, hãy dùng quá tải hàm thay vì hàm template. Bài tập I 1. Viết một chương trình, trong đó có hàm template tên là min(), trả nó về giá trò đối số nhỏ hơn trong hai giá trò đối số của hàm. Lấy ví dụ min(3,4) = 3, hoặc min('c', 'a') = 'a' . 2. Viết một chương trình, trong đó có hàm template tên là bubblesort(), thực hiện việc sắp xếp các dữ liệu kiểu số nguyên, số thực hoặc kiểu ký tự . Nếu thành công, hàm trả về giá trò 1, ngược lại hàm sẽ trả về trò là -1. Hàm có dạng int bubblesort (X a[], int n); với n xác đònh số lượng các phần tử của dãy a. 3. Viết một chương trình, trong đó có hàm template tên là find(), thực hiện việc tìm kiếm một đối tượng trên một dãy. Nếu tìm thấy, hàm trả về chỉ số của đối tượng tìm được, ngược lại hàm sẽ trả về trò là -1. Hàm có dạng int find(int object, int *list, int size); với size xác đònh số lượng các phần tử của dãy. Chương 10 Template điều khiển ngoại lệ 305 II/ Lớp template Lớp template đònh nghiã tất cả các thuật toán được dùng bởi lớp đó, tuy nhiên kiểu dữ liệu thực sự mà lớp này xử lý sẽ được đònh rõ dưới dạng tham số lúc tạo ra các đối tượng thuộc lớp template đó. • Khai báo template < class Ttype > class class_name { // body of class }; Ttype là tên lớp hình thức nó sẽ được xác đònh khi tạo ra một lớp. Khi cần thiết, có thể đònh nghiã lớp template với nhiều kiểu dữ liệu template bằng cách dùng một danh sách các tên kiểu hình thức được phân cách nhau bằng dấu phẩy. • Sau khi tạo ra lớp template, có thể sinh ra một lớp cụ thể từ lớp template class_name < type > object_name ; với type là tên thực của kiểu dữ liệu mà lớp đó xử lý. Các hàm thành phần của một lớp template cũng là các hàm template một cách tự động không cần phải dùng từ khoá template để khai báo tường minh cho các hàm đó. Ví dụ 2.1 Tạo ra lớp template cho một danh sách liên kết, dùng để lưu các ký tự. // A simple generic linked list. #include <iostream.h> template < class data_t > class list { data_t data; list *next; public: list( data_t d) ; void add(list *node) { node->next = this; Chửụng 10 Template vaứ ủieu khieồn ngoaùi leọ 306 next = 0; } list *getnext() { return next; } data_t getdata() { return data; } }; template < class data_t > list < data_t > :: list( data_t d) { data = d; next = 0; } int main() { list<char> start('a') ; list<char> *p, *last ; int i; // build a list last = &start; for(i=1; i<26; i++) { p = new list<char> ('a' + i) ; p->add(last); last = p; } // follow the list p = &start; while(p) { cout << p->getdata(); p = p->getnext(); } return 0; } . không cùng thực thi một công việc. void outdata(int i) { cout << i; } Chương 10 Template và điều khiển ngoại lệ 303 void outdata(double d) { cout <<. <class X> void swapargs(X &a, X &b) { X temp; temp = a; a = b; b = temp; } // This overrides the generic version of swapargs(). void swapargs(int

Ngày đăng: 27/12/2013, 23:39

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan