Trong bài viết này, chúng ta sẽ thảo luận về callback là gì và những loại callback nào chúng ta có thể có trong C ++ và cách thiết kế Callback dưới dạng con trỏ hàm.
Callback là gì?
Callback (gọi lại) là một hàm mà chúng ta chuyển đến các API khác làm đối số trong khi gọi chúng. Giờ đây, các API này sẽ sử dụng callback gọi lại hàm được cung cấp của chúng ta vào một thời điểm nào đó.
Có 3 kiểu callback trong c++
- Con trỏ hàm
- Đối tượng hàm
- Hàm lambda
Hành vi hoặc kết quả của API phụ thuộc vào hàm callback mà ta cung cấp, tức là nếu ta giữ nguyên đầu vào cho API và chỉ cần thay đổi callback thì đầu ra của API sẽ thay đổi. Hãy tìm hiểu điều này bằng cách,
Sử dụng con trỏ hàm như là một callback
Từ framework, ta có một API có thể tạo một thông điệp hoàn chỉnh từ các dữ liệu thô được cung cấp. API này sẽ thực hiện những bước sau:
- Thêm header và footer vào đoạn dư liệu thô để tạo ra thông điệp.
- Mã hóa toàn bộ thông điệp.
- Trả lại thông điệp.
Bây giờ API này biết header và footer là gì nhưng lại không biết về logic mã hóa chính xác, vì điều đó không được thiết lập trong framework, có thể thay đổi từ ứng dụng này sang ứng dụng khác. Vì logic mã hóa phụ thuộc vào ứng dụng, do đó trong API này cung cấp một điều khoản để truyền logic mã hóa như một con trỏ hàm gọi lại. API này sẽ gọi lại hàm của ứng dụng bằng cách gọi thông qua con trỏ hàm đã truyền này.
API của Framework chấp nhận callback với con trỏ hàm là một đối số như sau,
std::string buildCompleteMessage(std::string rawData, std::string (* encrypterFunPtr)(std::string) )
{
// Add some header and footer to data to make it complete message
rawData = "[HEADER]" + rawData + "[FooTER]";
// Call the callBack provided i.e. function pointer to encrypt the message
rawData = encrypterFunPtr(rawData);
return rawData;
}
Giờ thì, khi một ứng dụng gọi API này của framework để xây dựng thông báo, nó sẽ truyền một con trỏ đến hàm cục bộ của nó như một đối số.
Giả sử, ta có một hàm là một callback như bên dưới. Hàm mã hóa này sẽ tăng tất cả các ký tự trong thông điệp lên 1.
std::string encryptDataByLetterInc(std::string data)
{
for(int i = 0; i < data.size(); i++)
{
if( (data[i] >= 'a' && data[i] <= 'z' ) || (data[i] >= 'A' && data[i] <= 'Z' ) )
data[i]++;
}
return data;
}
Bây giờ, thử gọi API trên để tạo một thông điệp có hàm mã hóa như ta vừa mới tạo ra,
std::string msg = buildCompleteMessage("SampleString", &encryptDataByLetterInc);
std::cout<<msg<<std::endl;
Kết quả: [IFBEFS]TbnqmfTusjoh[GppUFS]
Tiếp theo, hãy tạo ra một hàm mã hóa khác. Lúc này, tất cả cá ký tự trong chuỗi sẽ bị giảm đi một.
std::string encryptDataByLetterDec(std::string data)
{
for(int i = 0; i < data.size(); i++)
{
if( (data[i] >= 'a' && data[i] <= 'z' ) || (data[i] >= 'A' && data[i] <= 'Z' ) )
data[i]--;
}
return data;
}
Và, kết quả khi gọi API
std::string msg = buildCompleteMessage("SampleString", &encryptDataByLetterDec);
std::cout<<msg<<std::endl;
là [GD@CDQ]R`lokdRsqhmf[EnnSDQ]
Ta thấy kết quả của lần gọi này khác với trước đó. Mặc dù giữ nguyên API và dữ liệu đã chuyển nhưng ta đã thay đổi hàm callback được truyền, dẫn đến hành vi hoặc kết quả của API đã thay đổi.
Vậy là chúng ta đã biết được như thế nào gọi là callback và cách sử dụng con trỏ hàm để truyền một callback. Trong phần tiếp theo, ta sẽ tìm hiều đối tương hàm gọi lại cũng như tại sao lại cần đối tượng này.
Để lại một bình luận