2010-09-01 46 views
11

C++ 11 có cung cấp các đại biểu không?Đại biểu trong C++ 11

Nếu không, cách tốt nhất (hiệu quả nhất) để làm điều gì đó tương tự trong C++ là gì? Boost.Signals? FastDelegate? Thứ gì khác?

+0

Whats sai với chức năng gợi ý? – alternative

+0

Tôi không thể sử dụng nó với phương thức lớp:/ – dot222

+0

có bạn có thể http: //www.parashift.com/C++ - faq-lite/pointers-to-members.html nhưng có thể có những điều tốt hơn để sử dụng ví dụ: Các hàm C++ không cần phải là các phương thức, hoặc bạn có thể biến lớp thành một hàm functor –

Trả lời

14

Bạn có thể nhận được ngữ nghĩa đại biểu giống như sử dụng bind để ràng buộc một hàm thành viên một trường hợp lớp:

#include <functional> 

struct C 
{ 
    void Foo(int) { } 
}; 

void Bar(std::function<void(int)> func) 
{ 
    func(42); // calls obj.Foo(42) 
} 

int main() 
{ 
    using namespace std::placeholders; 

    C obj; 
    Bar(std::bind(&C::Foo, obj, _1)); 
} 

Trong ví dụ này, Bar() mất bất cứ điều gì mà có một tham số duy nhất int và trả về void.

Trong main(), chúng tôi liên kết con trỏ với hàm thành viên C::Foo với phiên bản C có tên obj. Điều này cho chúng ta một đối tượng có thể được gọi với một tham số int đơn và trả về void.

Chúng tôi gọi Bar() với đối tượng này và Bar() thực hiện cuộc gọi obj.Foo(42).

+0

+1, hoặc bạn chỉ có thể biến C thành một hàm functor. –

+0

@jk: Chỉ đôi khi. Rõ ràng trong trường hợp này bạn có thể, nhưng tôi không có nhiều lớp trong ứng dụng của tôi mà chỉ có một thành viên chức năng :-) –

-1

Cơ chế C luôn luôn là con trỏ hàm & dùi cui (ngoại trừ qsort() và bsearch() không nhận được dùi cui).

Vì vậy, người ta sẽ luôn chuyển đối tượng lớp làm gậy.

ví dụ .:

class tp { 
    public: 
     tp() { n = 0; } 
     void m(int z) { printf("%d is %d\n", n++, z++); } 
     int n; 
}; 

void higher_func(int *opx, int cnt, void *handler(int itm, void *baton), void *baton) 
{ 
    for (int i = 0; i < cnt; i++) 
     handler(opx[itm], baton); 
} 

/* You would need to provide this stub -- potentially templateable */ 
void translate_baton(int itm, void *baton) { ((tp *)baton)->m(itm); } 

/* used like so: */ 
int main() 
{ 
    int array[7]; 

    //... 
    tp cx; 
    higher_func(array, 7, translate_baton, &cx); 
} 
+5

Câu hỏi này không phải là về C: cơ chế C có sẵn trong C + + nhưng điều đó không làm cho nó sự lựa chọn tốt nhất. –

+0

Tôi làm rất nhiều công việc với các đại biểu trong .NET và tin tôi theo cách này sẽ giúp tôi giải quyết rắc rối về cách thức của các đại biểu hơn là cách khác. – Joshua

0

Bạn không nhất thiết cần phải chờ đợi cho C++ 0x. Bạn có thể triển khai hầu hết các đại biểu trong tiêu chuẩn C++ 03 hiện tại. Bạn chỉ đơn giản là phải quá tải toán tử(), vì vậy bạn có thể gọi MyObjectFunctor functor; functor(); và vì hàm functor là một đối tượng, bạn có thể chuyển nó làm đại biểu/đối tượng thành các hàm;

phiên bản hiện tại của STL xác định tiêu đề <algorithm> cung cấp các chức năng sẵn sàng để sử dụng với Functors/Lambdas/Delegates.

ví dụ đơn giản về một hàm.

struct FunctorDelegate 
{ 
    // as so to delegate as a function that takes an int input 
    void operator()(int) 
    { 
     // do what I want 
    } 
}; 

int main() 
{ 
    //... do some stuffs with an std::vector<int> aRange; 
    FunctorDelegate functor; 
    std::for_each(aRange.begin(), arange.end(), functor); 
} 
+0

Những gì đại biểu có thể làm là khả năng lưu trữ, ví dụ, 'int A :: func1 (int, int)' hoặc 'int B :: func2 (int, int)' trong một biến (nói 'f'), vì vậy nó có thể được gọi là 'int v = f (a, 12, 34);' hoặc 'int v2 = f (b, 42, 24);'. Trong ví dụ của bạn, hàm functor có thể được gọi, nhưng nó không thể được coi là trừu tượng hóa kiểu hàm 'void (int)'. –

2

Bạn không cần C++ 0x. trong <functional> bạn có bind1stbind2ndmem_funmem_fun_ref. Bạn cũng có Boost.Bind để tổng quát tất cả các chức năng trên (IIRC).

Đi từ bộ nhớ ...

vector<Foo> foo = makeVector(); 
vector<Foo*> foop = makeVectorP(); 
vector<Bar> bar1,bar2,bar3,bar4; 
transform(foo.begin(), foo.end(), back_inserter(bar1), mem_fun_ref(&Foo::getBar)); 
transform(foop.begin(), foop.end(), back_inserter(bar2), mem_fun(&Foo::getBar)); 
transform(foo.begin(), foo.end(), back_inserter(bar3), bind1st(&bar_from_foo)); 
transform(foo.begin(), foo.end(), back_inserter(bar4), boost::bind(&bar_from_foo, _1)); 
+6

bind1st, bind2nd, mem_fun và mem_fun_ref không được dùng nữa trong C++ 11. –

1

Mặc dù std::function hoạt động độc đáo, tôi muốn chỉ ra mảnh đẹp mã này đại biểu, viết here (bao gồm cả ví dụ sử dụng!). Theo các tham chiếu và câu trả lời ở đó, bạn có thể đọc tất cả về cách lớp này được xây dựng và tại sao nó có thể nhanh hơn std::function.

Cũng lưu ý câu hỏi của tôi here cho một vấn đề tôi gặp phải với nó trên VS 2015.