Template là một khái niệm quan trọng trong C++, giúp bạn viết code linh hoạt và tái sử dụng được. Bài viết này sẽ đi sâu vào Template, đặc biệt là Function Template, cung cấp kiến thức nền tảng và ví dụ thực tế để bạn dễ dàng nắm bắt.
1. Template trong C++ là gì?
Template (khuôn mẫu) là một tính năng mạnh mẽ của C++, cho phép bạn viết các hàm và lớp làm việc với nhiều kiểu dữ liệu khác nhau mà không cần viết lại code cho từng kiểu. Template giúp code trở nên tổng quát và dễ bảo trì hơn.
- Template (khuôn mẫu): Một từ khóa trong C++, đại diện cho kiểu dữ liệu trừu tượng, tổng quát hóa các kiểu dữ liệu như
int,float,double,bool,… - Hai loại Template:
- Function Template (khuôn mẫu hàm)
- Class Template (khuôn mẫu lớp)
- Lợi ích: Template cho phép định nghĩa hàm và lớp một cách tổng quát, thay vì phải nạp chồng (overloading) cho từng kiểu dữ liệu khác nhau.
2. Cách sử dụng Function Template
Function Template (khuôn mẫu hàm) cho phép bạn tạo ra các hàm có thể hoạt động với nhiều kiểu dữ liệu khác nhau.
- Cú pháp khai báo:
template <class T>
T someFunction(T arg1, ...) {
// ...
}
Ví dụ: Hàm swapVal()
Xét ví dụ về hàm swapVal() để hoán đổi giá trị của hai biến:
void swapVal(int &a, int &b) {
int temp = a;
a = b;
b = temp;
}
Hàm swapVal(int &a, int &b) chỉ hoạt động với kiểu int. Để hoán đổi giá trị của hai biến kiểu double, char, string,… bạn cần nạp chồng hàm (overloading):
void swapVal(double &a, double &b) {
double temp = a;
a = b;
b = temp;
}
Việc nạp chồng hàm nhiều lần gây tốn thời gian và bộ nhớ. Để tối ưu, bạn có thể sử dụng Function Template:
template <class val>
void swapVal(val &a, val &b) {
val temp = a;
a = b;
b = temp;
}
Chương trình ví dụ:
#include <iostream>
#include <string>
using namespace std;
template <class val>
void swapVal(val &a, val &b) {
val temp = a;
a = b;
b = temp;
}
int main() {
int intX = 2, intY = 3;
double doubleX = 1.2, doubleY = 3.1;
string str1 = "Code", str2 = "Learn";
// Gọi hàm swapVal() với kiểu int
swapVal(intX, intY);
cout << "intX = " << intX << "tintY = " << intY << endl;
// Gọi hàm swapVal() với kiểu double
swapVal(doubleX, doubleY);
cout << "doubleX = " << doubleX << "tdoubleY = " << doubleY << endl;
// Gọi hàm swapVal() với kiểu string
swapVal(str1, str2);
cout << "Str1 = " << str1 << "tstr2 = " << str2 << endl;
return 0;
}
Kết quả:
intX = 3 intY = 2
doubleX = 3.1 doubleY = 1.2
Str1 = Learn str2 = Code
Giải thích:
- Tiền tố khuôn mẫu:
template <class val>template: Bắt buộc để khai báo template.class: Chỉ định rằngvallà một kiểu dữ liệu. C++ cũng cho phép sử dụng từ khóa “typename” ở vị trí này, nhưng nên ưu tiên sử dụngclass.val: Tên tham số kiểu, có thể thay thế bằng bất kỳ tên nào khác.
- Định nghĩa khuôn mẫu hàm:
swapVal()là một tập hợp các định nghĩa hàm.- Khi gọi
swapVal(intX, intY), trình biên dịch sẽ tạo ra một phiên bản của hàmswapVal()dành riêng cho kiểuint. Các kiểu dữ liệu khác (float,double,string) sẽ không được tạo ra cho đến khi được gọi.
- Gọi khuôn mẫu hàm:
swapVal(intX, intY): Trình biên dịch sử dụng khuôn mẫu để tạo ra hàmswapVal()cho hai tham số kiểuint.- Ưu điểm của template là bạn chỉ cần viết một hàm duy nhất, nó sẽ hoạt động với mọi kiểu dữ liệu.
Lưu ý khi viết Function Template:
- Mỗi tham số kiểu (
temptrong<class temp>) chỉ đại diện cho một kiểu dữ liệu duy nhất. Bạn không thể gán một biến kiểuintvà một biến kiểudoublecho cùng một tham số kiểu trong cùng một thời điểm.
Ví dụ sai:
#include <iostream>
using namespace std;
template <class temp>
void sum(temp intVal, temp doubleVal) {
cout << intVal + doubleVal << endl;
}
int main() {
sum(1, 1.1);
return 0;
}
Giải pháp:
Khai báo thêm một tham số kiểu:
#include <iostream>
using namespace std;
template <class temp, class temp1>
void sum(temp intVal, temp1 doubleVal) {
cout << intVal + doubleVal << endl;
}
int main() {
sum(1, 1.1);
return 0;
}
Kết quả: 2.1
- Khi sử dụng tham số kiểu làm kiểu trả về của hàm, hàm sẽ trả về kiểu dữ liệu của biến truyền vào, không phải một kiểu dữ liệu khác.
#include <iostream>
using namespace std;
template <class temp>
temp thuong(temp x1, temp x2) {
return (x1 * 1.0) / x2;
}
int main() {
int x1 = 1, x2 = 2;
cout << thuong(x1, x2) << endl;
return 0;
}
Kết quả: 0
Trong ví dụ trên, temp nhận kiểu int từ x1 và x2, do đó kết quả trả về là 0 thay vì 0.5. Cần cẩn thận trong trường hợp này.
3. Tổng kết
Bài viết này đã giới thiệu về Template trong C++, đặc biệt là Function Template. Bạn đã học được cú pháp, cách sử dụng và những lưu ý quan trọng khi viết Function Template.
Bài tập:
“Viết một hàm sử dụng khuôn mẫu để nhập vào một mảng có các giá trị kiểu tùy ý và trả về giá trị có số lần xuất hiện nhiều nhất trong mảng.”
Hy vọng bài viết này hữu ích cho bạn. Chúc bạn thành công trên con đường học lập trình C++!
