2013-06-25 2 views
-1

Я прочитал несколько сообщений об этом, но, похоже, не могу найти то, что я ищу, с примером кода, если кто-нибудь может мне помочь, я был бы очень признателен.C++ Указатель элемента функции

в моем заголовке я есть:

void addEvent(void (*func)(Pack *)); 

void triggerEvents(Pack *); 

std::list<void(*)(Pack *)> eventList; 

и в CPP файле

void DNetwork::addEvent(void (*func)(Pack *)){ 
    eventList.push_back(func); 
} 

void DNetwork::triggerEvents(Pack * pack){ 
    for (std::list<void (*)(Pack *)>::iterator it = eventList.begin(); it !=   eventList.end() ;it++){ 
     (*it)(pack); 
    } 
} 

Это прекрасно работает с бесплатными функциями, но когда я пытаюсь добавить функцию-член в этом списке я получаю ошибка. Кто-нибудь знает, как сохранить функцию-член (из объектов случайного класса) внутри указателя?

+0

Яп: 'ReturnType (TheClass :: * memberPointer) (аргументы, ...) = & TheClass :: aMemberFunction; ' –

+0

См. Раздел C++ FAQ 33: http://www.parashift.com/c++-faq/pointers-to-members.html – aschepler

+0

Да, но я хочу иметь возможность хранить указатели на функции из разных классов.Возможно ли иметь родительский класс для класса, который я хочу использовать, который может принимать функции так, чтобы список был следующим: std :: list eventList; –

ответ

1

Для функции члена вам нужна привязка. Функция-член - это «нормальная функция», которая имеет неявный параметр своего класса. Так что вам нужно связующее. Если вы используете C++ 11, вы можете использовать std :: bind и std :: function или вы можете использовать boost :: bind и boost :: function для кода не C++ 11.

typedef std::function< void (Pack*) > MyFunction; 
void addEvent(MyFunction f); 
void triggerEvents(Pack*); 
std::list<MyFunction> eventList; 

void DNetwork::addEvent(MyFunction f) 
{ 
    eventList.push_back(f); 
} 

void DNetwork::triggerEvents(Pack *pack) 
{ 
    for (auto it = eventList.begin(); it != eventList.end(); it++) 
    { 
     (*it)(pack); 
    } 
} 

Теперь, если у меня есть класс А с помощью метода doA(Pack*) Напишу:

A a; 
Pack pack; 
DNetwork d; 
d.addEvent(std::bind(&A::doA, &a, &pack)); 

Или еще лучше вы можете использовать Boost.Signal или вы можете использовать Publisher/Subcriber Pattern

Редактировать Как @ DavidRodríguez-dribeas предлагают: привязка не должна принимать аргумент пакета &, поскольку аргумент функции-члена предоставляется на p кружева вызова в triggerEvents. Правильный путь:

A a; 
Pack pack; 
DNetwork d; 
d.addEvent(std::bind(&A::doA, &a, std::placeholders::_1)); 
d.triggerEvents(&pack); 
+1

Связывание не должно принимать аргумент '& pack', поскольку аргумент функции-члена предоставляется в месте вызова в' triggerEvents' –

+0

@ DavidRodríguez-dribeas. Вы правы. Это должно быть 'd.addEvent (std :: bind (& A :: doA, & a, std :: placeholders :: _ 1));' –

-2

Если я понимаю вашу проблему, вы получаете сообщение об ошибке при попытке добавить функцию в список в addEvent?

Если вы хотите добавить указатель на нестатической функции члена класса убедитесь, что он правильный синтаксис ... например функция указатель на ау функцию члена в TestClass будет выглядеть так:

void * (TestClass:: *)() 
+1

Это не решит проблему. Нам нужен простой способ привязки к обычной функции и методу. Так что это функция juast + bind –

3

простой решение использует тип стирания на функции/функции указательного типа, для которых простой способ просто использует std::function<>:

std::list<std::function<void (Pack*)>; 

Затем вы можете инициализировать объекты function либо с помощью бесплатной функции, либо с помощью функции-члена (с помощью std::bind для связывания функции-члена с объектом, для которой ее вызывать) или даже с объектами функций (типы, которые предлагают operator()).

-1

Вы могли бы сделать перегрузку, такие как:

std::list<void(*)(Pack *)> eventList; 
void addEvent(void (*func)(Pack *)); 
template<typename T> 
void addEvent(void (T::*func)(Pack *)); 
namespace Abstraction { 
    template<typename T> 
    void abstractlyAddEvent(T, std::list<void(*)(Pack *)> *eventList); 
} 
+0

не нужно так много усложнять! просто привязка! –

+0

@ elvis.dukaj Не нужно меня отмечать, мое решение работает так же хорошо. :-( –