4

考虑三种实现C++中的例程的方法:通过函子,成员函数和非成员函数。例如,将成员函数作为参数传递给函数模板

#include <iostream> 
#include <string> 

using std::cout; 
using std::endl; 
using std::string; 

class FOO 
{ 
public: 
    void operator() (string word)   // first: functor 
    { 
    cout << word << endl; 
    } 

    void m_function(string word)   // second: member-function 
    { 
    cout << word << endl; 
    } 
} FUNCTOR; 


void function(string word)    // third: non-member function 
{ 
    cout << word << endl; 
} 

现在考虑一个模板函数来调用上面的三个功能:

template<class T> 
void eval(T fun) 
{ 
    fun("Using an external function"); 
} 

什么叫FOO::m_function通过EVAL的正确方法? 我想:

FUNCTOR("Normal call");    // OK: call to ‘void FOO::operator()(string)‘ 
eval(FUNCTOR);      // OK: instantiation of ‘void eval(T) [with T = FOO]’ 

function("Normal call");    // OK: call to ‘void function(string)’ 
eval(function);      // OK: instantiation of ‘void eval(T) [with T = void (*)(string)]’ 

FUNCTOR.m_function("Normal call"); // OK: call to member-function ‘FOO::m_function(string)’ 
eval(FUNCTOR.m_function);    // ERROR: cannot convert ‘FOO::m_function’ from type 
             //  ‘void (FOO::)(std::string) {aka void (FOO::)(string)}’ 
             //  to type ‘void (FOO::*)(std::basic_string<char>)’ 
             // In instantiation of ‘void eval(T) [with T = void (FOO::*)(string)]’: 
             // ERROR: must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘fun (...)’, e.g. ‘(... ->* fun) (...)’ 
+0

'错误:必须使用或“ - > *”来调用指针到成员函数'请问错误消息该行给出提示“*”? – PaulMcKenzie

+0

我想'的eval(T乐趣,O对象){对象。*的乐趣( “... ”)}'没有结果 – vagoberto

+0

使用'(对象。*的乐趣)(“ ...”)'代替 – vsoftco

回答

7

一个指向成员函数和函数指针是两个不同的东西。前者采用隐含的第一个参数,即this指针,或换句话说,指向要在其上调用成员函数的实例的指针。

通常情况下,为了能够通过成员函数的调用对象,你bind上它是被调用,然后用placeholders,表示稍后将传递给可调用参数的实例。在你的情况

eval(std::bind(&FOO::m_function, &FUNCTOR, std::placeholders::_1)); 

上面的第一个参数是bind要调用成员函数指针,第二个是指向上要调用m_functionFOO实例。最后一个是一个占位符,指示传递给由bind创建的可调用对象的第一个参数应在调用成员函数时使用。

另一种方法是将一个lambda表达式传递给eval,该表达式采用char const *(或std::string const&)参数并调用成员函数。

eval([](char const *c) { FUNCTOR.m_function(c); }); 

Live demo

+0

有关声明'm_function'为'static'?然后我就可以把它作为'的eval(FUNCTOR.m_function)'什么其他功能。我应该避免这个? – vagoberto

+0

@vsoftco唉,别提了。问题是,我们确实是会要绑定的东西,'mem_fn'缺少所需的功能。 – Potatoswatter

+2

@vagoberto如果'm_function'保证不会使用'FOO'的状态,那么它应该被声明为static,并且问题会消失。在创建一个没有状态的类之前总是要三思而行:除非涉及元编程,否则您确实需要一个名称空间。 – Potatoswatter

2

里面eval,你不能叫一个成员函数,因为你没有任何物体;

你可以去这样的:

template<class T, class U> 
void eval(T&& object, U fun) 
{ 
    (object.*fun)("Using an external function"); 
} 

然后

eval(FUNCTOR, &FOO::m_function); 
+0

好办法,但我有类似'eval'我不能编辑:( – vagoberto

相关问题