2013-02-01 263 views
5

C++中可能嗎? 例如,我有一個指向不帶參數,其返回類型爲void的函數:將指針指向功能對象的指針地址

void (*f)(); 

和和一個函數對象:

class A 
{ 
public: 
    void operator()() { cout << "functor\n"; } 
}; 

是否有可能分配給f地址一個A對象?當我打電話f()調用A仿函數?

我試過,但它不工作:

#include <iostream> 
using namespace std; 

class A 
{ 
public: 
    void operator()() { cout << "functorA\n"; } 
}; 

int main() 
{ 
    A ob; 
    ob(); 
    void (*f)(); 
    f = &ob; 
    f();  // Call ob(); 
    return 0; 
} 

我得到C:\Users\iuliuh\QtTests\functor_test\main.cpp:15: error: C2440: '=' : cannot convert from 'A *' to 'void (__cdecl *)(void)' There is no context in which this conversion is possible

有什麼辦法來實現這一目標?

+3

你不能只使用'std :: function '? – chris

+0

有沒有辦法用舊的標準來做到這一點,在C++ 11之前呢? –

回答

5

你不能做到這一點在您指定的方式打球,這是因爲:

  1. 操作者()必須是一個非靜態函數(標準要求)
  2. 一個指針指向一個非靜態函數必須有一個隱含的參數 - 的指針類實例
  3. 你到f()調用並不會給其對象A的實例你的函數被調用

使用C++ 11和std :: function的任何跡象,如斯蒂芬·羅蘭指出,可以做的伎倆 - 你會被指定的指針對象中的結合:

std::function<void(void)> f = std::bind(&A::operator(), &ob); 

(參見question上使用std ::上成員函數功能)

+1

+1:對於std :: bind –

2

是的,它有可能使用C++ 1/C++ 0x功能,但要實現這一點,您應該使用std :: function,它可以解決兩種類型的函數和對象函數。

#include <functional> 

class A 
{ 
public: 
    void operator()() { } 
}; 

int main() 
{ 
    std::function<void(void)> aFunction; 
    A ob; 

    aFunction = ob; 

// or as another user said 
// aFunction = std::bind(&A:operator(), &ob); 

    aFunction(); 

    void (*f)(); 

    aFunction = f; 

    aFunction(); 

    return 0; 
} 

,如果你堅持用C++ 03,你可以用std::mem_funstd::ptr_fun

3

如果使用C++ 11,可以使用std::function

#include <functional> 

std::function<void()> f; 

int main() 
{ 
    A ob; 
    ob(); 

    f = ob; // f refers to ob 
    f();  // Call ob(); 
    return 0; 
} 
1

怎麼樣的解決方法是這樣的:

基本上你想有調用成員函數和函數的常用方法。然後,也許你可以創建一個包裝器來代表一個函數或成員函數的泛型指針。假設您有Base類,並且您希望能夠調用所有派生類的operator()。然後,你也有一個function()要調用以及:如果您創建了一個包裝,讓您構建您的自定義指針(MyFncPtr

class Base 
{ 
public: 
    virtual void operator()() = 0; 
}; 

class A : public Base 
{ 
public: 
    void operator()(){ std::cout << "A()" << std::endl; } 
}; 

void function() 
{ 
    std::cout << "function" << std::endl; 
} 

typedef void (Base::*BaseFncPtr)(); 
typedef void (*FncPtr)(); 

class MyFncPtr 
{ 
public: 
    MyFncPtr(FncPtr f) : fnc(f), baseObj(NULL), baseFnc(NULL) { } 
    MyFncPtr(BaseFncPtr fPtr, Base* objPtr) : baseFnc(fPtr), baseObj(objPtr), fnc(NULL) { } 
    void invoke() 
    { 
     if (baseObj && baseFnc) 
      (baseObj->*baseFnc)(); 
     else if (fnc) 
      fnc(); 
    } 

private: 
    BaseFncPtr baseFnc; 
    Base* baseObj; 
    FncPtr fnc; 
}; 

你能做到像此:

A a; 
MyFncPtr myPtr(&Base::operator(), &a); 
myPtr.invoke(); 
MyFncPtr myPtr2(function); 
myPtr2.invoke(); 

輸出:

A() 
function 

希望這有助於:)

+0

請注意,這是最終解決方案的概念。當原始'baseObj'被破壞時,當你仍然保留'MyPtr'對象時,你應該考慮懸掛指針的問題等。可以使用智能指針,以便它變得更加適當的解決方案:) – LihO

+0

+1 for foraround新的C++ 11功能。謝謝! –

+0

@JohnSmith:不客氣:)是的,我想指出除了那些依賴於C++ 0x/C++ 11的解決方案外,還有其他解決方案;) – LihO