Sử Dụng Template Trong C Thế Nào (Phần 1)

Trong bài viết này mình sẽ hướng dẫn cách bạn tiếp cận tới một tri thức khá là quan yếu mà mỗi người học lập trình C++ đều phải biết và ứng dụng nó. Đó chính là Template.

1. Template trong C++ là gì?

  • Template (khuôn mẫu) là một từ khóa trong C++, và là một kiểu dữ liệu trừu tượng tổng quát hóa cho những kiểu dữ liệu int, float, double, bool…
  • Template trong C++ với 2 loại đó là operate template & class template.
  • Template giúp người lập trình khái niệm tổng quát cho hàm và lớp thay vì phải nạp chồng (overloading) cho từng hàm hay phương thức với những kiểu dữ liệu khác nhau.

2. Cách sử dụng template đối với hàm

  • Cú pháp khai báo hàm khuôn mẫu

template <class T> T someFunction(T arg1, …) { … }

Vì sao chúng ta phải sử dụng template nhỉ?

Khách hàng thử xem ví dụ đối với hàm swapVal() dưới đây rồi tự rút ra nhận xét cho riêng mình nhé.

void swapVal(int &a , int &b) { int temp; temp = a; a = b; b = temp; }

Hàm swapVal(int &a , int &b) chỉ ứng dụng cho 2 biến kiểu int, do đó muốn đổi 2 biến với những kiểu dữ liệu double, char, string… chúng ta phải overloading nó thêm 1 lần nữa

void swapVal(double &a , double &b) { double temp; temp = a; a = b; b = temp; }

Qua ví dụ trên chúng ta với thể thấy việc nạp chồng liên tục những hàm nhiều lần như vậy mất nhiều thời và bộ nhớ của máy tính, để tối ưu việc nạp chồng chúng ta sẽ xử lí chúng bằng cách viết một hàm khuôn mẫu swapVal như sau:

template <class val> void swapVal(val &a , val &b) { val temp; temp = a; a = b; b = temp; }

Chúng ta thử chạy xem sao nhé:

#embody <bits/stdc++.h> utilizing namespace std; template <class val> void swapVal(val &a , val &b) { val temp; temp = a; a = b; b = temp; } int foremost() { int intX = 2, intY = 3; double doubleX = 1.2, doubleY = 3.1; string str1 = "Code", str2 = "Study"; //gọi hàm swapVal() đối với 2 số nguyên swapVal(intX, intY); cout << "intX = " << intX << "tintY = " << intY << endl; //gọi hàm swapVal() đối với 2 số thực swapVal(doubleX, doubleY); cout << "doubleX = " << doubleX << "tdoubleY = " << doubleY << endl; //gọi hàm swapVal() đối với 2 chuỗi swapVal(str1, str2); cout << "Str1 = " << str1 << "tstr2 = " << str2 << endl; return 0; }

Sau lúc chạy chương trình sẽ với kết quả:

c

Qua ví dụ trên chúng ta với thể thấy kiểu dữ liệu của biến khái niệm chuẩn xác được quyết định ở thời khắc chạy, và chương trình ngắn gọn hơn rất nhiều so với nạp chồng từng hàm swapVal()

Giảng giải:

  • Tiền tố khuôn mẫu
    • template <class val>
      • Ở đây class là kiểu hoặc sự phân lớp nên nó ko phải là từ class chúng ta hay thấy ở trong lập trình hướng đối tượng.
      • C++ cho phép sử dụng từ khóa "typename" ở vị trí từ khóa class , tuy nhiên chúng ta nên sử dụng từ khóa class trong mọi trường hợp.(Trong phần sau mình sẽ nói rõ lúc nào sử dụng typename , lúc nào sử dụng class)
      • Trong thân khái niệm hàm, val được sử dụng giống như một kiểu bất kì trùng với kiểu dữ liệu truyền vào.
    • Từ val là tên trượng trưng cho class nên với thể được thay thế bằng bất kì từ nào khác chúng ta muốn.
  • Khái niệm khuôn mẫu hàm:
    • Khuôn mẫu hàm swapVal() là một tập hợp những khái niệm.
    • Lúc chúng ta chạy chương trình với đối số truyền vào hàm swapVal() là kiểu int thì lúc này trình biên dịch sẽ phát sinh khái niệm một hàm swapVal(int& a, int& b) mà ko phát sinh ra những khái niệm cho những đối số kiểu float , double hay string. Do vậy chúng ta với thể kết luận được rằng trình biên dịch chỉ phát sinh những khái niệm lúc được yêu cầu với điều kiện ta đã khái niệm cho tất cả những kiểu.
    • Qua đó ta với thể thấy ưu điểm vượt trội của template trong C++ là chúng ta viết một hàm khái niệm nó sẽ làm việc cho tất cả những kiểu với thể với.
  • Gọi khuôn mẫu hàm
    • Xét lời gọi hàm swapVal(intX,intY) bộ biên dịch C++ sử dụng khuôn mẫu để khởi tạo khái niệm hàm cho hai thông số int và tương tự với tất cả những kiểu khác.

Một số lưu ý lúc viết hàm template:

  • Một template <class temp> , temp chỉ với tác vụ khái niệm cho 1 kiểu dữ liệu duy nhất do đó chúng ta ko thể gán 1 biến kiểu int và double cho cùng 1 kiểu dữ liệu temp trong cùng một thời khắc.

Ví dụ:

#embody <bits/stdc++.h> utilizing namespace std; template <class temp> void sum(temp intVal , temp doubleVal) { cout<<int1+double1; } int foremost() { int intVal = 1; double doubleVal = 1.1; sum(intVal , doubleVal); return 0; }

Chương trình sẽ báo lỗi như ảnh dưới

Annotation%202020 07 11%20182300

Để giải quyết vấn đề đó thì ta khai báo thêm một kiểu dữ liệu tổng quát vào như sau:

#embody <bits/stdc++.h> utilizing namespace std; template <class temp , class temp1> void sum(temp intVal , temp1 doubleVal) { cout<<int1+double1; } int foremost() { int intVal = 1; double doubleVal = 1.1; sum(intVal , doubleVal); return 0; }

Lúc chạy chương trình ta sẽ nhận được kết quả là 2.1, từ đây chúng ta với thể thấy rằng lúc ta muốn sử dụng bao nhiêu kiểu dữ liệu tổng quát thì khai báo bấy nhiêu.

  • Lúc lấy temp làm kiểu dữ liệu trả về cho hàm, chúng cũng chỉ nhận kiểu dữ liệu của biến trả về theo kiểu dữ liệu của biến truyền vào mà ko trả về một kiểu dữ liệu khác được

#embody <bits/stdc++.h> utilizing namespace std; template <class temp> temp thuong(temp x1, temp x2) { return (x1*1.0)/x2; } int foremost() { int x1 = 1 , x2 = 2; cout<<thuong(x1,x2); return 0; }

Kết quả của chương trình ra 0 bởi vì temp sẽ nhận kiểu dữ liệu theo biến x1 , x2 đã được khái niệm trước kiểu int vì thế giá trị trả về là 0 mà ko thể trả về kết quả như mong muốn là 0.5, do lúc trình biên dịch chạy nó sẽ tự động nhận kiểu dữ liệu của biến truyền vào. Vì vậy lúc viết khuôn hàm mẫu chúng ta nên kỹ càng trong trường hợp trả về kết quả như này nhé.

Tạm Kết

Vậy là chúng ta đã tìm hiểu được một phần của template trong C++, cụ thể là operate template. Qua bài viết này mình mong người dùng nhớ được cú pháp, những sử dụng của operate template và những lưu ý lúc viết hàm template.

Mình mong những với thể làm được bài tập nhỏ mình đưa ra sau đây: "Viết một hàm với sử dụng khuôn mẫu nhập vào một mảng với những giá trị với kiểu tùy ý và trả về giá trị với số lần xuất hiện nhiều nhất trong mảng." (bạn nào cần code thì remark gmail nhé)

Mong người dùng price và remark ý kiến ở phía dưới để những bài sau mình ra tốt hơn. Cảm ơn người dùng hứa hẹn gặp lại người dùng vào phần tiếp theo Class Template.