tài liệu c++
K ỹ thuật lập trình Phần III: Lập trình tổng quát 0101010101010101100001 0101010101010101100001 0101010101010101100001 0101010100101010100101 0101010100101010100101 0101010100101010100101 1010011000110010010010 1010011000110010010010 1010011000110010010010 1100101100100010000010 1100101100100010000010 1100101100100010000010 0101010101010101100001 0101010101010101100001 0101010101010101100001 0101010100101010100101 0101010100101010100101 0101010100101010100101 1010011000110010010010 1010011000110010010010 1010011000110010010010 1100101100100010000010 1100101100100010000010 1100101100100010000010 0101010101010101100001 0101010101010101100001 0101010101010101100001 0101010100101010100101 0101010100101010100101 0101010100101010100101 1010011000110010010010 1010011000110010010010 1010011000110010010010 1100101100100010000010 1100101100100010000010 1100101100100010000010 y = A*x + B*u; x = C*x + d*u; StateController start() stop() LQGController start() stop() Chương 9: Khuôn mẫu hàm và khuôn mẫulớp 12/25/2007 2 Chương 9: Khuôn mẫu hàm và khuôn mẫulớp Nộidung chương 9 9.1 Khuôn mẫuhàm -Vaitròcủa khuôn mẫuhàm - Định nghĩa khuôn mẫuhàm -Sử dụng khuôn mẫuhàm 9.2 Khuôn mẫulớp - Định nghĩa khuôn mẫulớp -Dẫnxuất khuôn mẫulớp -Vídụ khuôn mẫulớp Vector 3 Chương 9: Khuôn mẫu hàm và khuôn mẫulớp 9.1 Khuôn mẫuhàm(function template) Vấn ₫ề: Nhiều hàm chỉ khác nhau về kiểu dữ liệu tham số áp dụng, không khác nhau về thuật toán Ví dụ: int max(int a, int b) { return (a > b)? a : b; } double max(double a, double b) { return (a > b)? a : b; } . Các ví dụ khác: các hàm swap, sort, find, select, . Bản chất của vấn ₫ề? Nằm ở ngôn ngữ lập trình còn thấp, chưa gần với tư duy của con người! Giải pháp: Tổng quát hóa các hàm chỉ khác nhau về kiểu dữ liệu áp dụng thành khuôn mẫu hàm. 4 Chương 9: Khuôn mẫu hàm và khuôn mẫulớp Định nghĩakhuônmẫuhàm Ví dụ tổng quát hóa hàm max ₫ể có thể áp dụng cho nhiềukiểu dữ liệu khác nhau: template <typename T> T max(T a, T b) { return (a > b)? a : b; } Ví dụ tổng quát hóa hàm swap: template <class X> void (X& a, X& b) { X temp = a; a = b; b = temp; } Mộtkhuônmẫuhàminline: template <typename T> inline T max(T a, T b) { return (a > b)? a : b;} Sử dụng từ khóa typename hoặc class ₫ể khai báo tham số khuôn mẫu 5 Chương 9: Khuôn mẫu hàm và khuôn mẫulớp Khai báo và sử dụng khuôn mẫuhàm Ví dụ sử dụng khuôn mẫuhàmmax template <class T> T max(T a, T b); template <class T> void swap(T&, T&); void main() { int N1 = 5, N2 = 7; double D1 = 5.0, D2 = 7.0; int N = max(N1,N2); // max<int>(int,int) char c = max('c','a'); // max<char>(char, char) double D = max(D1,D2); // max<double>(double, double) swap(N1,N2); // swap<int>(int&,int&) swap(D1,D2); // swap<double>(double&,double&) D = max(D1,A1); // error: ambiguous N = max('c',A1); // error: ambiguous D = max<double>(D1,A1);// OK: explicit qualification N = max<int>('c',A); // OK: explicit qualification } Khuôn mẫuhàm Hàm khuôn mẫu 6 Chương 9: Khuôn mẫu hàm và khuôn mẫulớp Khả năng áp dụng khuôn mẫuhàm Khả năng áp dụng một khuôn mẫuhàmlàvôtận, nhưng không phảiápdụng ₫ượcchotấtcả các ₫ốisố khuôn mẫu Ví dụ: Điềukiệnràngbuộc ₫ốivớikiểudữ liệucóthể áp dụng trong khuôn mẫu hàm max là phải có phép so sánh lớnhơn(>): template <class T> inline T max(T a, T b) { return (a > b)? a : b;} => Đốivớicáckiểudữ liệumới, muốnápdụng ₫ượcthìcầnphải nạpchồng toán tử so sánh > Tuy nhiên, khả năng áp dụng ₫ượcchưachắc ₫ãcóý nghĩa Ví dụ: Xác ₫ịnh chuỗikýtự₫ứng sau trong hai chuỗichotrước theo vầnABC char city1[] = "Ha Noi", city2[] = "Hai Phong"; char* city = max(city1,city2); // ??? // max<char*>(char*,char*) 7 Chương 9: Khuôn mẫu hàm và khuôn mẫulớp Nạpchồng khuôn mẫuhàm Mộtkhuônmẫuhàmcóthể₫ượcnạpchồng bằng hàm cùng tên . char* max(char* a, char* b) { if (strcmp(a,b)) . } void f() { char c = max('H','K'); // max<char>(char,char) char city1[] = "Ha Noi", city2[] = "Hai Phong"; char* city = max(city1,city2); // max(char*,char*) . } .hoặcbằng mộtkhuônmẫu hàm cùng tên (khác số lượng các tham số hoặckiểucủaítnhấtmộtthamsố), ví dụ: template <class T> T max(T a, T b, T c) { .} template <class T> T max(T* a, int n) { .} nhưng không ₫ượcnhư thế này: template <class X> X max(X a, X b) { .} 8 Chương 9: Khuôn mẫu hàm và khuôn mẫulớp Tham số khuôn mẫu Tham số khuôn mẫuhàmcóthể là mộtkiểucơ bảnhoặcmột kiểudẫnxuất, nhưng không thể là mộtbiếnhoặcmộthằng số: template <class T> max(T a, T b) { . } // OK template <int N> max(int* a) { . } // error Mộtkhuônmẫuhàmcóthể có hơnmộtthamsố kiểu: template <class A, class B> void swap(A& a, B& b) { A t = a; a = b; // valid as long as B is compatible to A b = t; // valid as long as A is compatible to B } void f() { double a = 2.0; int b = 3; swap(a,b); // swap<double,int>(double&,int&) swap(b,a); // swap<int,double)(int&, double&) } 9 Chương 9: Khuôn mẫu hàm và khuôn mẫulớp Thông thường, tham số khuôn mẫuxuấthiệnítnhấtmộtlầnlà kiểuhoặckiểudẫnxuấttrựctiếpcủa các tham biến: template <class X> void f1(X a, int b) { .} template <class X> void f2(X* b) { .} template <class X,class Y> void f3(Y& a, X b) { .} Theo chuẩn ANSI/ISO C++, tham số khuôn mẫu không bắtbuộc phảixuấthiệntrongdanhsáchthambiến, nhưng cầnlưuý khi sử dụng. Ví dụ #include <stdlib.h> template <class X> X* array_alloc(int nelem) { return (X*) malloc(nelem*sizeof(X)); } void main() { double* p1 = array_alloc(5); // error! double* p2 = array_alloc<double>(5); // OK! . free(p2); } 10 Chương 9: Khuôn mẫu hàm và khuôn mẫulớp Khuôn mẫu hàm và hàm khuôn mẫu Khuôn mẫuhàmchỉ₫ưaracáchthứcthựchiệnvàsử dụng một thuậttoánnào₫ómộtcáchtổng quát Trong khi biên dịch khuôn mẫu hàm, compiler chỉ kiểmtravề cú pháp, không dịch sang mã ₫ích Mã hàm khuôn mẫu ₫ượccompiler tạora(dựa trên khuôn mẫu hàm) khi và chỉ khi khuôn mẫuhàm₫ượcsử dụng vớikiểucụ thể Nếumộtkhuônmẫuhàm₫ượcsử dụng nhiềulầnvớicáckiểu khác nhau, nhiều hàm khuôn mẫusẽ₫ượ ctạoratương ứng Nếumộtkhuônmẫuhàm₫ượcsử dụng nhiềulầnvớicáckiểu tương ứng giống nhau, compiler chỉ tạoramột hàm khuôn mẫu.