2015-04-08 80 views
2

我一直在使用C++中的函数指针,似乎已经发现了一些问题。我通过一个简单的例子来演示重现错误。函数指针在参数对象中使用函数

我的头文件

class MyClass 
{ 
public: 
    void MyFunction(int i); 
    MyClass(); 
    ~MyClass(); 
}; 

和cpp文件

#include "MyClass.h" 
#include <iostream> 
#include <functional> 
using namespace std; 

MyClass::MyClass() 
{ 
    //doesn't work 
    function<void(int)> func = &MyClass::MyFunction; 
} 

void MyClass::MyFunction(int i) 
{ 
    cout << i << endl; 
} 

在cpp文件我想创建一个指向的MyFunction的构造。它在第506行的功能文件中给出了错误error C2664: 'void std::_Func_class<_Ret,int>::_Set(std::_Func_base<_Ret,int> *)' : cannot convert argument 1 from '_Myimpl *' to 'std::_Func_base<_Ret,int> *'。它对于无参数方法很好,但不适用于它们。有谁知道为什么,以及如何解决它?

+3

非静态成员函数需要一个对象。 – chris

+0

所以我不能从课堂上做到这一点?或者有没有办法用我完全缺少的这个关键字来做到这一点? –

回答

3

您可以使用this并将正在构造的对象绑定到该函数。举例来说,如果你的构造是这样的:

MyClass::MyClass() 
{ 
    function<void(int)> func = bind(&MyClass::MyFunction, this, placeholders::_1); 
    func(6); 
} 

你创建了一个MyClass实例:

MyClass instance; 

然后6将被打印到标准输出。

+0

这工作,谢谢。你能解释一下占位符:: _ 1是什么吗? –

+1

占位符基本上是作为[currying](http://stackoverflow.com/a/160286/2297365)函数的一种方式。所有非静态成员函数实际上都有一个隐含的第一个参数,即类本身的一个实例。你正在做的是将一个实例绑定到第一个参数,而第二个参数未指定。占位符为您提供了表达这一点的语义。 – huu

+1

例如,如果放置一个'6'而不是占位符,那么函数将被完全指定,并且只能将其称为'func()'。这会打印出一个'6'到标准输出。 – huu

3

您还可以在使用std::mem_fn C++ 11,它包装一个成员函数/变量到一个可调用关闭

#include <iostream> 
#include <functional> 

class MyClass 
{ 
public: 
    MyClass() 
    { 
     auto func = std::mem_fn(&MyClass::MyFunction); 
     func(this, 42); // call it on the current instance 
    } 
    void MyFunction(int i) 
    { 
     std::cout << i << std::endl; 
    } 
}; 

int main() 
{ 
    MyClass foo; 
} 

或者,您可以明确指定要调用的成员函数指针的实例

MyClass() 
{ 
    auto func = &MyClass::MyFunction; 
    (this->*func)(42); // call it on the current instance 
} 

尤其要注意的是,std::function<void(int)>不能转换成指向成员函数的指针。看到相关的Using generic std::function objects with member functions in one class 这就是为什么使用autostd::mem_fn摆脱所有的痛苦。

+1

这是一个很好的答案。它可以让你把函数视为C++对待它,作为一个函数将类的实例作为第一个参数,以及其后的所有其他参数。 – huu

+0

谢谢,我最近发现了'std :: mem_fn',我认为这对于日常的C++工作来说是一个很好的包装 – vsoftco