5

考虑在 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) (...)’
4

2 回答 2

9

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

通常,为了能够将成员函数作为可调用对象传递,您bind需要在其上调用它的实例,然后使用placeholders来指示稍后将传递给可调用对象的参数。在你的情况下

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

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

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

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

现场演示

于 2015-06-03T01:36:47.343 回答
2

在里面eval,你不能调用成员函数,因为你没有任何对象;

你可以这样做:

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

接着

eval(FUNCTOR, &FOO::m_function);
于 2015-06-03T01:35:40.103 回答