2013-06-25 226 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

雅普:'返回類型(theClass描述:: * memberPointer)(參數,...)= theClass描述:: aMemberFunction; ' – 2013-06-25 18:19:34

+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,或者你可以對非C++ 11代碼使用boost :: bind和boost :: function。

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); 
    } 
} 

現在如果我有A類與方法doA(Pack*)我會寫:

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

甚至更​​好,你可以使用Boost.Signal或者您可以使用Publisher/Subcriber Pattern

編輯 由於@DavidRodríguez-dribeas建議:綁定不應該採取& pack參數,因爲成員函數的參數在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的AA成員函數看起來像:

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

這不能解決問題。我們只需要一個簡單的方法來綁定到普通的函數和方法。所以它是juast函數+ bind –

3

簡單溶液使用上的功能/功能指針類型類型擦除時,更簡單的方法是隻使用std::function<>,其中:

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

然後,您可以使用自由函數或成員函數(通過std::bind將成員函數與要調用它的對象綁定在一起)甚至函數對象(提供operator()的類型)來初始化function對象。

-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無需標記我,我的解決方案也能正常工作。 :-( –