Template trong C++

Khi học về lập trình hướng đối tượng (OOP) trong ngôn ngữ C++, trong quá trình lập trình, chắc ai cũng gặp trường hợp phải overload lại các hàm để dùng cho mỗi kiểu dữ liệu tương ứng, thì trong C++ có hỗ trợ cho chúng ta giải quyết vấn đề trên, Trong bài viết dưới đây eLib sẽ hướng dẫn bạn tiếp cận tới một kiến thức khá là quan trọng mà mỗi người học lập trình C++ đều phải biết và áp dụng nó. Đó chính là Template. Cùng theo dõi nhé!

Template trong C++

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

Template trong C++ là nền tảng của lập trình tổng quát (generic programming), tức là viết code theo các mà độc lập với bất kỳ kiểu cụ thể nào.

Một Template là một blueprint hoặc là phương thức để tạo một lớp hoặc một hàm tổng quát. Các Library Container như Iterator và các thuật toán là các ví dụ của lập trình tổng quát và đã được phát triển bởi sử dụng khái niệm Template.

Mỗi container có một định nghĩa đơn, ví dụ vector, nhưng chúng ta có thể định nghĩa nhiều loạt vector khác nhau, ví dụ: vector <int> hoặc vector <string>.

Template là từ khóa trong C++, chúng ta có thể hiểu rằng là nó một kiểu dữ liệu trừu tượng, đặc trưng cho các kiểu dữ liệu cơ bản. Template là từ khóa báo cho trình biên dịch rằng đoạn mã sau đây định nghĩa cho nhiều kiểu dữ liệu và mã nguồn của nó sẽ được biên dịch sinh ra tương ứng cho từng kiểu dữ liệu trong quá trình biên dịch. Có hai kiểu Template trong C++:

  • Function Template: là một khuôn mẫu hàm, cho phép định nghĩa các hàm tổng quát thao tác cho nhiều kiểu dữ liệu.
  • Class template: là một khuôn mẫu lớp, cho phép định nghĩa các lớp tổng quát cho nhiều kiểu dữ liệu.

2. Function Template trong C++

Cú pháp Function Template trong C++:

emplate <class kieu_du_lieu> kieu_tham_chieu ten_ham(danh_sach_tham_so) {
   // code
}

Trong đó, kieu_du_lieu là một tên một kiểu dữ liệu được sử dụng bởi hàm. Tên này có thể được sử dụng bên trong định nghĩa hàm.

Ví dụ: Function Template trong C++ trả về giá trị lớn nhất của hai giá trị:

#include <iostream>
#include <string>

using namespace std;

template <typename T>
inline T const& Max (T const& a, T const& b) {
    return a < b ? b:a;
}

int main () {
    int i = 39;
    int j = 20;
    cout << "Max(i, j): " << Max(i, j) << endl;

    double f1 = 13.5;
    double f2 = 20.7;
    cout << "Max(f1, f2): " << Max(f1, f2) << endl;

    string s1 = "Hello";
    string s2 = "C++";
    cout << "Max(s1, s2): " << Max(s1, s2) << endl;

    return 0;
}
Kết quả:
Max(i, j): 39
Max(f1, f2): 20.7
Max(s1, s2): Hello

3. Class Template trong C++

Giống như khi chúng ta có thể định nghĩa Function Template, chúng ta cũng có thể định nghĩa Class Template trong C++. Cú pháp chung của định nghĩa Class Template trong C++ là:

template <class kieu_du_lieu> class ten_lop {
    .
    .
    .
}

Trong đó, kieu_du_lieu là tên kiểu, mà sẽ được xác định khi một lớp được khai báo. Bạn có thể định nghĩa nhiều hơn một kiểu dữ liệu tổng quát (generic) bởi sử dụng một danh sách phân biệt nhau bởi dấu phảy.

Ví dụ: định nghĩa lớp Stack và triển khai các phương thức tổng quát để push và pop các phần tử từ Stack đó. (Stack: ngăn xếp, push: thêm nút mới vào đỉnh stack, pop: thao tác lấy 1 phần tử từ đỉnh stack).

#include <iostream>
#include <vector>
#include <cstdlib>
#include <string>
#include <stdexcept>

using namespace std;

template <class T>
class Stack {
   private:
      vector<T> elems;    // cac phan tu

   public:
      void push(T const&);  // push phan tu vao stack
      void pop();               // phan tu pop
      T top() const;            // tra ve phan tu tren cung
       
      bool empty() const {      // tra ve true neu trong
         return elems.empty();
      }
};

template <class T>
void Stack<T>::push (T const& elem) {
   // append copy of passed element
   elems.push_back(elem);   
}

template <class T>
void Stack<T>::pop () {
   if (elems.empty()) {
      throw out_of_range("Stack<>::pop(): empty stack");
   }
    
   // xoa phan tu cuoi cung
   elems.pop_back();        
}

template <class T>
T Stack<T>::top () const {
   if (elems.empty()) {
      throw out_of_range("Stack<>::top(): empty stack");
   }
    
   // tra ve ban copy cua phan tu cuoi cung
   return elems.back();     
}

int main() {
   try {
      Stack<int> intStack;
      Stack<string> stringStack;

      // push int vao stack
      intStack.push(7);
      cout << intStack.top() <<endl;

      // push string vao stack
      stringStack.push("hello");
      cout << stringStack.top() << std::endl;
      stringStack.pop();
      stringStack.pop();
   } catch (exception const& ex) {
      cerr << "Exception: " << ex.what() <<endl;
      return -1;
   }
}

Kết quả:

7
hello
Exception: Stack<>::pop(): empty stack

Trên đây là bài viết của eLib.VN về Template trong C++. Việc sử dụng “template” làm giảm rất nhiều thời gian và công sức phải code lại một hàm mà dùng cho nhiều kiểu dữ liệu, dễ dàng bảo trì, phát triển hay thay đổi  mã nguồn. Hãy thử áp dụng và trãi nghiệm, chúc các bạn thành công!

Ngày:27/10/2020 Chia sẻ bởi:Xuân Quỳnh

CÓ THỂ BẠN QUAN TÂM