2010-02-28 21 views
21

Gần đây tôi phát hiện ra rằng trong C++ bạn có thể quá tải "chức năng gọi là" nhà điều hành, theo một cách kỳ lạ, trong đó bạn phải viết hai cặp ngoặc đơn để làm như vậy:Làm thế nào có thể hữu ích khi quá tải toán tử "gọi hàm"?

class A { 
    int n; 
public: 
    void operator()() const; 
}; 

Và sau đó sử dụng nó theo cách này:

A a; 
a(); 

Khi nào điều này hữu ích?

+3

Đọc về các đối tượng chức năng. http://en.wikipedia.org/wiki/Function_object – AnT

Trả lời

27

này có thể được sử dụng để tạo "functors", đối tượng mà hành động như chức năng:

class Multiplier { 
public: 
    Multiplier(int m): multiplier(m) {} 
    int operator()(int x) { return multiplier * x; } 
private: 
    int multiplier; 
}; 

Multiplier m(5); 
cout << m(4) << endl; 

Các bản in trên 20. Bài viết trên Wikipedia được liên kết ở trên cung cấp thêm các ví dụ đáng kể.

+3

Và lý do chính bạn muốn các functors là có các hàm bậc cao hơn trong C++. –

+1

Bạn có thể mở rộng số này, ví dụ nhân với m lần đầu tiên bạn gọi nó, nhân với m + 1 lần thứ hai, v.v. Các chức năng thông thường không thể lưu bất kỳ thông tin trạng thái nào giữa các cuộc gọi, nhưng functors có thể. – MatrixFrog

+3

Vâng, bạn luôn có thể sử dụng các biến tĩnh trong một hàm để cung cấp cho nó trạng thái (hoặc globals - shudder). Nhưng cả hai đều rất xấu và dễ bị lỗi. (Tôi muốn sử dụng một functor thay thế .. nhưng nó là có thể) –

1

Nếu bạn đang tạo một lớp đóng gói một con trỏ hàm, điều này có thể làm cho việc sử dụng trở nên rõ ràng hơn.

4

Thuật toán được triển khai bằng mẫu không quan tâm liệu điều được gọi là hàm hay hàm functor, nó quan tâm đến cú pháp. Hoặc là tiêu chuẩn (ví dụ: for_each()) hoặc của riêng bạn. Và functors có thể có nhà nước, và làm tất cả mọi thứ khi họ được gọi. Hàm chỉ có thể có trạng thái với biến cục bộ tĩnh hoặc biến toàn cầu.

15

Có ít hơn một cú pháp đạt được khi sử dụng toán tử() cho đến khi bạn bắt đầu sử dụng mẫu. Nhưng khi sử dụng các mẫu, bạn có thể xử lý các hàm thực và hàm functors (các lớp hoạt động như các hàm) theo cùng một cách.

class scaled_sine 
{ 
    explicit scaled_sine(float _m) : m(_m) {} 
    float operator()(float x) const { return sin(m*x); } 
    float m; 
}; 

template<typename T> 
float evaluate_at(float x, const T& fn) 
{ 
    return fn(x); 
} 

evaluate_at(1.0, cos); 
evaluate_at(1.0, scaled_sine(3.0)); 
+0

Yep; các đối tượng giống như hàm thực sự hữu ích nhất khi bạn gõ đủ yếu. C + + đã không có điều đó, nhưng các mẫu làm. –

+0

Typo trong scaled_sine constructor Tôi nghĩ vậy. –

0

Trình biên dịch cũng có thể nội tuyến functor và cuộc gọi hàm. Nó không thể inline một con trỏ hàm, tuy nhiên. Bằng cách này, việc sử dụng toán tử gọi hàm có thể cải thiện đáng kể hiệu năng khi nó được sử dụng ví dụ với các thuật toán thư viện C++ chuẩn.

Các vấn đề liên quan