Проблема с указателем на функцию-член - PullRequest
2 голосов
/ 25 октября 2010

В приведенном ниже коде (см. Комментарий):

#include "stdafx.h"

#include <iostream>
using std::cout;

struct Base
{
 void fnc()
 {
  cout << "Base::fnc()";
 }

};

struct Impl
{
 void* data_;
 Impl(void (Base::*fp)())
 {
  fp();//HERE I'M INVOKING IT - I'M DOING SOMETHING WRONG!
 }
};
int _tmain(int argc, _TCHAR* argv[])
{
 return 0;
}  

Ошибка
"Ошибка 1 ошибка C2064: термин не оценивает функцию, принимающую 0 аргументов"это работает и как это исправить?

Ответы [ 5 ]

5 голосов
/ 25 октября 2010

Это не работает, потому что fp не указатель на функцию, а указатель на член.

Как это легко исправить, используйте его так, как следует: someinstance.*fp();

2 голосов
/ 25 октября 2010

Проблема в том, что вы вызываете функцию как бесплатную функцию, когда это не так.Это функция-член, и вам нужно вызывать ее в контексте объекта:

(obj.*f)();

Boost.Bind предлагает идиоматический способ решения этой проблемы:

#include<boost/bind.hpp>

// ...
Impl i(boost::bind(&Base::fnc, obj));

Вы можете определитьконструктор Impl выглядит так:

#include<boost/function.hpp>

// ...
Impl(boost::function<void ()> fnc)
{
    fnc();  // boost::bind translates it to obj.fnc()
}

Если только объект Impl знает, на какой объект вызывать функцию, то вы можете использовать заполнители Boost.Bind:

Impl i(boost::bind(&Base::fnc, boost::_1));

И тогда конструктор Impl будет похож на

Impl(boost::function<void (Base)> fnc, Base& b)
{
    fnc(b);  // boost::bind translates it to b.fnc()
}

Иногда разумнее использовать шаблоны на стороне, которая принимает функтор:

template<class Op>
Impl(Op fnc) { ... }

, потому что тогда клиентможет передать любую функцию-член, с или без повышения.Но цена в том, что у вас могут быть трудные для понимания сообщения об ошибках компилятора.

1 голос
/ 25 октября 2010

Вы можете прочитать этот FAQ по указателям на функции-члены. Особенно они настоятельно рекомендуют вам определить макрос для этих вызовов:

#define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember))

1 голос
/ 25 октября 2010
typedef  int (MyClass::*memberPointer_t)(int);

...

memberPointer_t mb = &MyClass::function;
MyClass* object = getObject();

int returnValue = (object->*mb)(3);

...

Поскольку это указатель на функцию-член, вы должны вызвать ее для объекта и использовать оператор -> * или. * Для ее вызова.

1 голос
/ 25 октября 2010

Вам нужна база для вызова функции.

Возможно, вы ищете что-то более похожее на bind () и функцию <>, которые позволят вам связать экземпляр и функцию-член в функторе, который можетбыть просто вызванным как функция.

...