boost::function
cho phép bất cứ thứ gì có operator()
chữ ký phù hợp được ràng buộc dưới dạng tham số và kết quả của ràng buộc của bạn có thể được gọi với một tham số int
, vì vậy nó có thể được liên kết với function<void(int)>
.
Đây là cách nó hoạt động (mô tả này áp dụng cho std::function
):
boost::bind(&klass::member, instance, 0, _1)
trả về một đối tượng như thế này
struct unspecified_type
{
... some members ...
return_type operator()(int i) const { return instance->*&klass::member(0, i);
}
trong đó dấu return_type
và int
được suy ra từ chữ ký của klass::member
, và con trỏ hàm và tham số ràng buộc trên thực tế được lưu trữ trong đối tượng, nhưng điều đó không quan trọng
Hiện nay, boost::function
không thực hiện bất kỳ kiểm tra kiểu nào: Nó sẽ lấy bất kỳ đối tượng nào và bất kỳ chữ ký nào bạn cung cấp trong tham số mẫu của nó và tạo một đối tượng có thể gọi theo chữ ký của bạn và gọi đối tượng. Nếu điều đó là không thể, đó là lỗi biên dịch.
boost::function
thực sự là một đối tượng như thế này:
template <class Sig>
class function
{
function_impl<Sig>* f;
public:
return_type operator()(argument_type arg0) const { return (*f)(arg0); }
};
nơi return_type
và argument_type
được trích xuất từ đâu Sig
và f
được phân bổ động trên heap. Điều đó cần thiết để cho phép các đối tượng hoàn toàn không liên quan với các kích thước khác nhau liên kết với boost::function
.
function_impl
chỉ là một lớp trừu tượng
template <class Sig>
class function_impl
{
public:
virtual return_type operator()(argument_type arg0) const=0;
};
Lớp thực hiện tất cả công việc, là một lớp cụ thể có nguồn gốc từ boost::function
. Có một cho mỗi loại đối tượng mà bạn chỉ địnhboost::function
template <class Sig, class Object>
class function_impl_concrete : public function_impl<Sig>
{
Object o
public:
virtual return_type operator()(argument_type arg0) const=0 { return o(arg0); }
};
Điều đó có nghĩa là trong trường hợp của bạn, nhiệm vụ tăng cường chức năng:
- khởi tạo một kiểu
function_impl_concrete<void(int), unspecified_type>
(tất nhiên đó là thời gian biên dịch)
- tạo một đối tượng mới thuộc loại đó trên heap
- gán đối tượng này cho thành viên f của hàm boost ::
Khi bạn gọi đối tượng hàm, nó sẽ gọi hàm ảo của đối tượng triển khai của nó, đối tượng này sẽ hướng lệnh gọi đến hàm ban đầu của bạn.
KHUYẾN CÁO: Lưu ý rằng những cái tên trong phần giải thích này được cố tình tạo ra. Bất kỳ điểm nào giống với người thật hoặc nhân vật ... bạn biết điều đó. Mục đích là để minh họa các nguyên tắc.