2013-02-01 43 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