2013-08-09 58 views
13

Tôi đã viết một chương trình nhỏ mà tôi đang cố truyền con trỏ tới hàm thành viên của một lớp đến một hàm khác. Bạn có thể vui lòng giúp tôi và nơi tôi đang đi sai ..?Chuyển một con trỏ tới hàm thành viên của lớp như một tham số

#include<iostream> 
using namespace std; 
class test{ 
public: 
     typedef void (*callback_func_ptr)(); 
     callback_func_ptr cb_func; 

     void get_pc(); 

     void set_cb_ptr(void * ptr); 

     void call_cb_func(); 
}; 
void test::get_pc(){ 
     cout << "PC" << endl; 
} 
void test::set_cb_ptr(void *ptr){ 
     cb_func = (test::callback_func_ptr)ptr; 
} 
void test::call_cb_func(){ 
      cb_func(); 
} 
int main(){ 
     test t1; 
      t1.set_cb_ptr((void *)(&t1.get_pc)); 
     return 0; 
} 

Tôi gặp lỗi sau khi tôi cố gắng biên dịch nó.

error C2276: '&' : illegal operation on bound member function expression 
+0

Tôi luôn tìm thấy http://www.newty.de/fpt/index.html rất hữu ích. – arne

+2

Chức năng thành viên không hoạt động. Loại bạn cần là 'void (test :: *) (void *)' ... –

+1

Kerrek SB là đúng. Tuy nhiên nếu bạn có ý định gọi cùng một thành viên cho các lớp khác nhau và các trường hợp bạn nên suy nghĩ về thừa kế và ảo ... –

Trả lời

19

Bạn không thể truyền con trỏ hàm tới void*.

Nếu bạn muốn có một con trỏ hàm để trỏ đến một hàm viên bạn phải khai báo kiểu như

ReturnType (ClassType::*)(ParameterTypes...) 

Hơn nữa bạn không thể khai báo một con trỏ hàm để một hàm thành viên bị ràng buộc, ví dụ

func_ptr p = &t1.get_pc // Error 

Thay vào đó bạn phải có được địa chỉ như thế này:

func_ptr p = &test::get_pc // Ok, using class scope. 

Cuối cùng, khi bạn thực hiện một cuộc gọi đến một con trỏ hàm trỏ đến một hàm thành viên, bạn phải gọi nó với một thể hiện của lớp rằng hàm là thành viên của. Ví dụ:

(this->*cb_func)(); // Call function via pointer to current instance. 

Dưới đây là ví dụ đầy đủ với tất cả các thay đổi được áp dụng:

#include <iostream> 

class test { 
public: 
    typedef void (test::*callback_func_ptr)(); 
    callback_func_ptr cb_func; 
    void get_pc(); 
    void set_cb_ptr(callback_func_ptr ptr); 
    void call_cb_func(); 
}; 

void test::get_pc() { 
    std::cout << "PC" << std::endl; 
} 

void test::set_cb_ptr(callback_func_ptr ptr) { 
    cb_func = ptr; 
} 

void test::call_cb_func() { 
    (this->*cb_func)(); 
} 

int main() { 
    test t1; 
    t1.set_cb_ptr(&test::get_pc); 
    t1.call_cb_func(); 
} 
+1

void test :: call_cb_func() {(this -> * cb_func)(); Một NEVER không muốn gọi hàm bằng con trỏ từ bên trong đối tượng. Do đó, 'cái này' trong ví dụ là một lời giải thích hoàn toàn vô dụng. Cho rằng C++ là cú pháp có thể vô nhân đạo nhất ngoài hex, người ta không thể đơn giản đoán cách gọi hàm từ đối tượng KHÁC. –

2

Ngoài câu trả lời SNPs, bạn cũng có thể sử dụng một function wrapper từ C++ 11 để lưu trữ một lambda chức năng:

#include <iostream> 
#include <functional> 

class test 
{ 
    public: 
    std::function<void()> Func; 
    void get_pc(); 
    void call_cb_func(); 
    void set_func(std::function<void()> func); 
}; 

void test::get_pc() 
{ 
    std::cout << "PC" << std::endl; 
} 

void test::call_cb_func() 
{ 
    Func(); 
} 

void test::set_func(std::function<void()> func) 
{ 
    Func = func; 
} 

int main() { 
    test t1; 
    t1.set_func([&](){ t1.get_pc(); }); 
    t1.call_cb_func(); 
}