Vietnamese Developers’ Blog

STL Function Object và các ứng dụng (1)

Posted in C/C++ by kiennguyen on November 23, 2007

Function Object là gì?

Function object là một object được sử dụng như một function. Với một function object của lớp Foo, khi viết Foo() nghĩa là chúng ta đang gọi đến operator() của lớp Foo. Viết một function object nghĩa là viết operator() cho một lớp. Chúng ta đã biết operator của một lớp được viết như sau

class Foo
{
  public:

    return_type operator() ( parameter list ) {

      statements;

    }

    /* Các public member khác */

  private:

    /* Các private member */

};

Cài đặt cụ thể cho operator() tùy thuộc vào ngữ cảnh sử dụng của function object. Qua cái nhìn đầu tiên, chúng ta thấy rằng cách viết này chính là sự phức tạp hóa của một hàm bình thường sau đây

return_type foo( parameter list ) {

  statements;

}

Sự phức tạp hóa này mang lại ba lợi ích

1- Các function object là các object, bởi vậy chúng có trạng thái, còn các hàm bình thường thì không.
2- Các function object thuộc về một lớp nào đó. Bởi vậy, chúng ta có thể tham số hóa các kiểu dữ liệu bên trong function object thông qua template.
3- Các function object thường chạy nhanh hơn các hàm thông thường.

Không nên mất thời gian suy nghĩ về ba lợi ích này làm gì! Hãy nghiên cứu các ứng dụng của function object, chúng ta sẽ dễ dàng hiểu được những lợi ích của chúng.

Ứng dụng của function object

Các function object được sử dụng trong hai trường hợp sau đây
1- Làm tiêu chí sắp xếp cho các container
2- Làm tham số cho các STL algorithm
Việc một function object được sử dụng ở đâu sẽ quyết định cách viết operator() của lớp đó.

Function Object làm tiêu chí sắp xếp cho các container

Trong phần này, chúng ta sẽ xem xét các ứng dụng của function object trong việc tạo ra các tiêu chí sắp xếp cho các STL set. Các ví dụ này có thể mở rộng cho các STL associative container khác như multiset, map, multimap.

Khi chúng ta đưa các phần tử vào một set, chúng sẽ được sắp xếp sao cho hai phần tử liên tiếp phải thỏa mãn tiêu chí sắp xếp dành cho set đó. Nếu các phần tử của set là các kiểu cơ bản như int hay string, chúng ta có thể sử dụng các tiêu chí sắp xếp sẵn có như greater hay less. Ví dụ dòng khai báo dưới đây

std::set< std::string, greater > strSet;

khai báo một set với các phần tử là các STL string được sắp xếp theo thứ tự tăng dần. Tuy nhiên, nếu các phần tử cần đưa vào set có kiểu do người dùng định nghĩa, ví dụ là các đối tượng của một lớp, thì làm sao để xác định thứ tự của chúng trong set? Có hai cách thực hiện: Một là vẫn sử dụng các tiêu chí sẵn có là less và greater. Tuy nhiên, cách này chỉ thực hiện được nếu lớp đã định nghĩa sẵn operator < (cho tiêu chí less) hoặc operator > (cho tiêu chí greater). Không phải lớp nào cũng cung cấp sẵn các operator này, mà không phải lúc nào chúng ta cũng có quyền “nhảy” vào để thêm mã cho lớp, mà giả sử chúng ta có quyền đi nữa thì cũng không nên làm phức tạp hóa một lớp sẵn có. Cách thứ hai là chúng ta tự định nghĩa một tiêu chí sắp xếp mới, đây chính là lúc cần đến function object. Xem ví dụ sau đây: Giả sử chúng ta cần lưu các đối tượng của lớp Person vào một set. Định nghĩa của lớp Person như sau:

(more…)