2009-01-27 44 views
6

Tôi đang cố chuyển con trỏ tới hàm được xác định trong một lớp vào một lớp khác. Sau nhiều nghiên cứu, tôi tin rằng cú pháp của tôi là chính xác, nhưng tôi vẫn nhận được lỗi trình biên dịch. Dưới đây là một số mã trong đó chứng tỏ vấn đề của tôi:không thể chuyển con trỏ tới hàm giữa các lớp

class Base 
{ 
public: 
    BaseClass(); 
    virtual ~BaseClass(); 
}; 

class Derived : public Base 
{ 
public: 
    // assign strFunction to the function pointer passed in 
    Derived(string (*funPtr)(int)) : strFunction(funPtr); 
    ~Derived(); 

private: 
    // pointer to the function that is passed in 
    string (*strFunction)(int value); 
}; 

class MainClass 
{ 
public: 
    MainClass() 
    { 
     // allocate a new Derived class and pass it a pointer to myFunction 
     Base* myClass = new Derived(&MainClass::myFunction);  
    } 

    string myFunction(int value) 
    { 
     // return a string 
    } 
}; 

Khi tôi cố gắng biên dịch mã này, lỗi tôi nhận được là

error: no matching function for call to 'Derived::Derived(string (MainClass::*)(int))'

Tiếp theo

note: candidates are: Derived::Derived(string (*)(int))

Bất kỳ ý tưởng gì tôi có thể đang làm sai?

Trả lời

8

cú pháp của bạn là chính xác cho con trỏ hàm kiểu C. Thay đổi nó như thế này:

Derived(string (MainClass::*funPtr)(int)) : strFunction(funPtr) {} 

string (MainClass::*strFunction)(int value); 

nhớ để gọi strFunction, bạn sẽ cần một thể hiện của một đối tượng MainClass. Thường thì tôi thấy hữu ích khi sử dụng typedef.

typedef string (MainClass::*func_t)(int); 
func_t strFunction; 

Derived(func_t funPtr) : strFunction(funPtr) {} 
+0

và những gì về nếu các lớp học được tách rời và bạn không thể chỉ định 'MainClass :: * funPtr'? – fduff

+0

Sau đó, tôi khuyên bạn nên sử dụng một thư viện chung như tạo tham số một hàm 'boost :: ' và chuyển hàm với 'boost :: bind' –

+0

tx nhưng dự án không tăng cường là gì? 'std :: function()' và 'std :: bind()' chỉ có sẵn trong C++ 11 mà chúng ta không có. – fduff

0

Phương pháp đối tượng có đối số "này" ẩn. Nếu bạn chuyển phương thức cho lớp khác, cái gì sẽ được điền vào đối số "này"? Bạn có thể làm điều đó với các phương thức tĩnh (Class).

2

Con trỏ hàm (là con trỏ đến hàm không liên kết) và con trỏ tới phương thức (đó là con trỏ đến hàm không tĩnh ràng buộc với định nghĩa lớp), khác nhau trong c++. Điều này là do các phương thức không tĩnh có một đối số ngụ ý this yêu cầu chúng luôn được gọi trong ngữ cảnh của một thể hiện của lớp của chúng.

Bạn đang cố gắng chuyển một con trỏ phương thức tới một hàm tạo có một con trỏ hàm. Mà sẽ không làm việc.

+0

Điều đó có ý nghĩa. – Chris

4

Có, loại &MainClass::myFunction là loại con trỏ đến thành viên trong khi string(*)(int) là loại con trỏ đến hàm. Chúng không tương thích khi bạn phải sử dụng một tham chiếu hoặc con trỏ tới một cá thể lớp và sử dụng toán tử. * Hoặc -> * để sử dụng một con trỏ tới thành viên, trong khi con trỏ tới một hàm không được gắn vào một lớp và có thể được gọi trực tiếp.

4

Bạn đang cố gắng để vượt qua một con trỏ tới một hàm thành viên của lớp MainClass, nhưng chức năng hy vọng một con trỏ đến một bình thường, tức là phi thành viên, chức năng. Tóm tắt tốt là here

Sự khác biệt là quan trọng vì hàm thành viên có thông số bổ sung ẩn cho biết chức năng con trỏ "này" để áp dụng hàm. Vì vậy, các loại con trỏ không thể hoán đổi cho nhau.

0

Khi cảnh báo trình biên dịch cho biết, các con trỏ hàm thành viên hoàn toàn khác với các con trỏ hàm thường.

2

Một vấn đề cú pháp:


    // assign strFunction to the function pointer passed in 
    Derived(string (*funPtr)(int)) : strFunction(funPtr); 

thay thế cho:


    // assign strFunction to the function pointer passed in 
    Derived(string (*funPtr)(int)) : strFunction(funPtr) {}; 
1

Bạn có thể muốn xem xét sử dụng std::tr1::bindstd::tr1::function tương tự như sau (chưa được kiểm tra) mã:

class Derived: public Base 
{ 
    public: 
    typedef std::tr1::function<string(int)> StringFunc; 

    Derived(StringFunc); 

    ... 

    private: 
    StringFunc strFunction; 
} 

và trong hàm dựng của MainClass:

myBase = new Derived(std::tr1::bind(&MainClass::myFunction, *this, _1); 

Hàm liên kết về cơ bản liên kết hàm thành viên với một đối tượng cụ thể. Mà sẽ chăm sóc con trỏ này được chèn bởi trình biên dịch.

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