Function Pointer
Bài viết về function pointer được trích dịch từ tài liệu này: http://www.newty.de/fpt/index.html
1 Giới thiệu
Function Pointer cung cấp một kỹ thuật lập trình cực kỳ thú vị, hiệu quả và “đầy màu sắc”. Chúng ta có thể sử dụng nó để thay thế câu lệnh switch/if, xây dựng quá trình late-binding hoặc implement hàm callback. Tiếc thay, có thể vì sự phức tạp của nó mà nó được đề cập rất ít trong hầu hết sách và tài liệu. Nếu có thì nó chỉ được trình bày một cách rất tóm tắt và sơ sài. Thực ra thì nó ít gây ra lỗi hơn so với pointer bình thường bởi vì chúng ta không bao giờ phải allocate hoặc de-allocate bộ nhớ cả. Tất cả việc chúng ta cần làm là hiểu nó làm gì và học cú pháp của nó. Nhưng hãy luôn tâm niệm rằng: hãy tự hỏi bạn có thực sự cần đến function pointer hay không? Rất tuyệt để thể hiện cách thức late-binding, thế nhưng sử dụng cấu trúc hiện tại của C++ làm cho đoạn mã trở nên dễ đọc và rõ ràng hơn. Một khía cạnh khác của late-binding là runtime: nếu bạn gọi một virtual function, chương trình sẽ xác định hàm nào được gọi. Nó làm điều đó bằng cách sử dụng V-Table mà chứa tất cả những hàm có thể gọi. Điều đó có vẻ hơi lãng phí mỗi lần gọi, và có thể bạn sẽ tiết kiệm một chút nếu sử dụng function pointer thay vì virtual function. Cũng có thể không …
1.1 Function Pointer là gì?
Function pointer là một pointer mà nó chỉ đến địa chỉ của một hàm. Bạn phải luôn giữ trong đầu rằng một chương trình chạy sẽ chiếm một không gian bộ nhớ xác định trong bộ nhớ chính. Cả đoạn chương trình thực thi đã được dịch từ mã mà bạn viết và các biến sử dụng đều được đưa vào trong không gian bộ nhớ này. Vì vậy một function trong chương trình của bạn không có gì khác hơn là một địa chỉ trong bộ nhớ.
1.2 Thay thế câu lệnh Switch như thế nào?
Khi chúng ta muốn gọi một hàm DoIt() ở một label xác định trong chương trình, chúng ta phải để lời gọi tới hàm DoIt() tại label đó. Sau đó biên dịch và mỗi khi chương trình chạy tới label đó thì hàm DoIt() sẽ được gọi. Mọi thứ đều ok, nhưng sẽ làm gì nếu giả sử chúng ta không biết tại thời điểm build-time (thời gian dịch) hàm nào sẽ được gọi? Nghĩa là chỉ đến lúc chạy ta mới biết ở label đó thì nên chạy DoIt() hay một hàm nào khác. Đó chính là lúc chúng ta muốn sử dụng đến callback-function hoặc là sử dụng kỹ thuật lấy ra từ một “pool” chứa các possible function. Tuy nhiên thì chúng ta có thể giải quyết vấn đề này bằng cách sử dụng lệnh switch, và lựa chọn lời gọi đến hàm thích hợp ở những nhánh khác nhau tùy theo giá trị biểu thức của switch. Nhưng vẫn có một cách khác là sử dụng function pointer. Trong ví dụ sau đây chúng ta thực hiện nhiệm vụ của bốn toán tử toán học cơ bản (+, -, *, /). Cách đầu tiên sử dụng switch và cách thứ hai sử dụng function pointer.
3 comments