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

相關問題