Template in C++

•Mục đích của template (mẫu) là hỗtrợtái sửdụng mã.

•Có 2 loại mẫu: hàm mẫu (template function) và lớp

mẫu (template class).

•Hàm/lớp mẫu là hàm/lớp tổng quát (generic

function/class), không phụthuộc kiểu dữliệu.

–Mã người dùng phải khai báo kiểu dữliệu cụthểkhi sử

dụng hàm/lớp mẫu.

• Khai báo hàm/lớp mẫu chỉtạo “khung”.

– Trình biên dịch sẽtạo mã thực thi từ“khung” chỉkhi nào

lớp/hàm mẫu được dùng đến.

pdf11 trang | Chuyên mục: C/C++ | Chia sẻ: dkS00TYs | Lượt xem: 1889 | Lượt tải: 0download
Tóm tắt nội dung Template in C++, để xem tài liệu hoàn chỉnh bạn click vào nút "TẢI VỀ" ở trên
1Template in C++
2
• Mục đích của template (mẫu) là hỗ trợ tái sử dụng mã.
• Có 2 loại mẫu: hàm mẫu (template function) và lớp 
mẫu (template class).
• Hàm/lớp mẫu là hàm/lớp tổng quát (generic 
function/class), không phụ thuộc kiểu dữ liệu.
– Mã người dùng phải khai báo kiểu dữ liệu cụ thể khi sử 
dụng hàm/lớp mẫu.
• Khai báo hàm/lớp mẫu chỉ tạo “khung”. 
– Trình biên dịch sẽ tạo mã thực thi từ “khung” chỉ khi nào 
lớp/hàm mẫu được dùng đến.
3Hàm mẫu
• Giải thuật độc lập với kiểu dữ liệu được xử lý.
Ví dụ: Tìm số lớn nhất: max = (a > b) ? a : b;
• Cài đặt bằng ngôn ngữ lập trình
int max(int a, int b) { 
return a > b ? a : b; 
} 
int m = 43, n = 56; 
cout << max(m, n) << endl; // 56
double x = 4.3, y = 5.6;
cout << max(x, y) << endl; // 5
• Quá tải hàm max() là một giải pháp.
double max(double a, double b);
4
• Quá tải hàm sẽ gây ra tình trạng “lặp lại mã”.
→ Sử dụng hàm mẫu.
template 
TYPE max(const TYPE & a, const TYPE & b) {
return a > b ? a : b;
}
int m = 43, n = 56;
cout << max(m, n) << endl; // 56
double x = 4.3, y = 5.6;
cout << max(x, y) << endl; // 5.6
• Chương trình vẫn thực thi với kiểu dữ liệu string. 
string s = "abc", t = "xyz"; 
cout << max(s, t) << endl; // xyz
5template 
int count(const TYPE *array, int size, TYPE val) {
int cnt = 0;
for (int i = 0; i < size; i++)
if (array[i] == val) cnt++;
return cnt;
}
double b[3] = {3, -12.7, 44.8}; 
string c[4] = {"one", "two", "three", "four"};
cout << count(b, 3, 3) << endl; // illegal
cout << count(c, 4, "three"); // illegal
cout << count(b, 3, 3.0) << endl; // legal
cout << count(c, 4, string(“three”)); // legal
6
template 
void dim2(TYPE ** & prow, int rows, int cols) { 
TYPE * pdata = new TYPE [rows * cols]; 
prow = new TYPE * [rows]; 
for (int i = 0; i < rows; i++) 
prow[i] = pdata + i * cols; 
}
Mô phỏng mảng hai chiều
7template 
void display(TYPE **a, int rows, int cols) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++)
cout << a[i][j] << ' ';
cout << endl;
}
}
/* ----------------------------------------- */
template 
void free2(TYPE **pa) { // free 2D memory
delete [] *pa; // free data
delete [] pa; // free row pointers
}
8
int main() {
int **a; 
dim2(a, rows, cols); // 2D array of integers
int inum = 1;
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
a[i][j] = i + j; 
display(a, rows, cols);
free2(a); 
double **b; 
dim2(b, rows, cols); // 2D array of doubles
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
b[i][j] = (i + j) * 1.1; 
display(b, rows, cols); 
free2(b);
9Complex **a; 
dim2(a, 3, 4);
for (i = 0; i < 3; i++) 
for (j = 0; j < 4; j++) {
a[i][j].real(1.1);
a[i][j].imag(2.2);
}
display(a, 3, 4); 
free2(a);
…
}
10
Lớp mẫu
• Lớp mẫu cho phép tạo ra những lớp tổng quát.
– Loại trừ khả năng sử dụng lặp mã lệnh khi xử lý những 
kiểu dữ liệu khác nhau.
– Thiết kế thư viện thuận tiện và dễ quản lý hơn.
• Những lớp chỉ làm việc trên một kiểu dữ liệu thì không 
nên tổng quát hóa.
– Lớp Complex: chỉ làm việc với double.
– Lớp String (user-defined): chỉ làm việc với ký tự.
• Những lớp chứa (container class) như Stack, List, 
… nên được tổng quát hóa.
11
class Stack { 
private:
int *v; // pointer to integer data
int top; // top of Stack
int len; // length of Stack
public:
Stack(int size = MAXLEN) : top(0) {
v = new int[len = size];
}
~Stack() { delete [] v; }
void push(int d) { v[top++] = d; }
int pop() { return v[--top]; }
bool empty() const { return top == 0; }
bool full() const { return top == len; }
int length() const { return len; }
int nitems() const { return top; }
};
12
template 
class Stack {
private:
TYPE * v;
int top;
int len;
void copy(const Stack &);
void free() { delete [] v; }
public:
Stack(int size = MAXLEN);
Stack(const Stack & s) { copy(s); }
~Stack() { free(); }
void push(const TYPE & d) { v[top++] = d; }
TYPE pop() { return v[--top]; }
Stack & operator=(const Stack &s);
…
};
13
template 
Stack::Stack(int size) {
v = new TYPE [len = size];
top = 0;
}
template 
void Stack::copy(const Stack & s) {
v = new TYPE [len = s.len];
top = s.top;
for (int i = 0; i < len; i++)
v[i] = s.v[i];
}
14
template 
Stack & Stack::operator=(const
Stack & s) {
if (this != &s) {
free();
copy(s);
}
return *this;
}
template 
void store(const TYPE * b, int len) {
Stack s(len);
…
}
15
int main() {
Stack s(10);
s.push(100);
cout << s.pop() << endl;
Stack * st = new Stack(5);
st->push(“abc”);
cout pop() << endl;
delete st;
int buf[10]; 
store(buf, 10);
string title[20];
store(title, 20);
…
}
16
Xây dựng lớp mảng 1 chiều tổng quát
• Mảng 1 chiều của C++ gặp những hạn chế sau:
– Khai báo kích thước mảng tĩnh.
– Không kiểm tra giới hạn mảng.
– Không cho phép gán hai mảng cùng kiểu.
• Mảng 1 chiều tổng quát sẽ khắc phục những hạn chế 
trên.
Array a(3)
v
len 3
0 1 2a
17
template 
class Array { 
private:
TYPE * v;
int len;
void range(int) const;
void copy(const Array &);
void free() { delete [] v };
public:
Array(int length = 1);
Array(const Array & a);
~Array() { free(); }
Array & operator=(const Array &);
TYPE & operator[](int);
const TYPE & operator[](int) const;
int length() const { return len; }
};
18
class ArrayError {
private:
char buf[80];
public:
ArrayError(int s) { 
sprintf(buf, "%d is an illegal length", s);
}
ArrayError(int index, int maxindex) { 
sprintf(buf, "subscript %d out of bounds,
max subscript = %d", index, maxindex - 1);
}
void response() const { cerr << buf << endl; }
};
19
template 
void Array::range(int i) const {
if (i = len) throw ArrayError(i, len);
}
template 
Array::Array(int length) {
if (length <= 0) throw ArrayError(length); 
v = new TYPE [len = length];
}
template 
Array::Array(const Array & a) { 
copy(a); 
}
20
template 
Array & Array::operator=
(const Array & a) {
if (this != &a) {
free();
copy(a);
}
return *this;
}
template 
ostream & operator<<(ostream & os, const
Array & a) {
for (int i = 0; i < a.length(); i++)
os << a[i] << ' '; 
return os;
}
21
template 
TYPE & Array::operator[](int i) {
range(i);
return v[i];
}
template 
const TYPE & Array::operator[](int i) const {
range(i);
return v[i];
}
22
int main() {
try {
Array a(10), b(10);
for (int i = 0; i < a.length(); i++)
a[i] = i + 1;
cout << a << endl;
b = a; 
cout << b << endl;
Array c(10);
for (i = 0; i < c.length(); i++)
c[i] = 0.5 * i;
const Array d = c; 
cout << d << endl;
}
catch (const ArrayError & e) {
e.response(); return 1;
}
return 0;
}

File đính kèm:

  • pdfTemplateTrongC++.pdf