2010-09-17 29 views
1

我創建了一個非常簡單的Tree實現,我想能夠將函數對象傳遞給我的traverse()功能。例如如果函數對象有多個參數,它會是什麼樣子?

template<class T> 
class MyTree 
{ 
public: 

    void traverse(MyFunction f) { 
     traverse(root, f); 
    } 
private: 
     MyTreeNode<T>* root; 
     void traverse(MyTreeNode<T>*, MyFunction f); 
}; 

的事情是,我怎麼申報f,如果我想在一些參數傳遞,以及有問題的節點? (指向其他structs)。或者,任何人都可以指向我的一些教程的方向嗎?

+0

http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=141 – DumbCoder 2010-09-17 11:36:02

+0

難道我怎麼申報「F」或我怎麼申報「MyFunction的」? – Chubsdad 2010-09-17 14:23:26

+0

@Chubsdad,我該如何聲明'MyFunction'。 – BeeBand 2010-09-17 15:39:35

回答

1

在這個階段你可以做不同的事情。

舊C風格類型的解決方案:可以傳遞函數指針:

template <typename T> 
void MyTree<T>::traverse(void (*function)(MyTreeNode<T>*, int)); 

這將需要爲自變量的函數指針(自由功能),其採用一個指向MyTreeNode<T>對象作爲第一個參數和一個整數作爲第二個參數。你可以typedef功能類型來緩解用法:

template <typename T> 
class MyTree { 
public: 
    typedef void func(MyTreenode<T>*, int);  // typedef the function type 
    typedef void (*pfunc)(MyTreenode<T>*, int); // or the function pointer 
    void traverse(func* function); 
    void traverse2(pfunc function); 
}; 

你可以使用任何可調用事情作爲參數與模板的幫助:

template <typename T> 
class MyTree { 
public: 
    template <typename Functor> 
    void traverse(Functor f); 
}; 

其中在最簡單的方法是簡單如果您將參數類型自由釋放,但是如果嘗試傳遞一個可調用的實體並接受一組不同的參數,則錯誤消息可能不那麼容易解析。在內部,你可以使用f就好像它是一個功能,但在外部可以是一個函數或函數對象,包括std::bind

你可以向前走一步,實際上執行的結果(C++ 0x中)或boost::bindtraverse功能你會使用std::function(同樣,C++ 0x中)使用的參數簽名或boost::function

template <typename T> 
class MyTree { 
public: 
    void traverse(std::function< void (MyTreeNode<T>*, int)> f); 
}; 

這種解決方案的優點是很明顯你將如何使用傳入的參數(如函數指針方法):您將調用f(x, y)其中xMyTreeNode<T>*y是一個整數。同時,您通過std::bind(C++ 0x)或boost::bind提供模板化解決方案的通用性,可用於使不同實體適應function<...>參數,包括自由函數,函數對象,成員函數......

2

一種可能性是使用boost::function和定義一個函數式,其僅需要你的節點作爲參數。然後,只要綁定其他參數,就可以根據您喜歡的任何函數創建boost::function對象。

template<class T> 
class MyTree 
{ 
public: 
    typedef boost::function< void (MyTreeNode<T>*) > MyFunction; 

    void traverse(MyFunction f) { 
     traverse(root, f); 
    } 
private: 
     MyTreeNode<T>* root; 
     void traverse(MyTreeNode<T>*, MyFunction f); 
}; 

tree.traverse(boost::bind(&func_with_args, _1, arg1, arg2)); 
2

你可以使它成爲一個模板成員函數,

template<class T> 
class MyTree 
{ 
public: 

    template<typename Functor> 
    void traverse(Functor f) { 
     traverse(root, f); 
    } 
private: 
     MyTreeNode<T>* root; 

     template<typename Functor> 
     void traverse(MyTreeNode<T>* node, Functor f) { 
     f(node->value); 
     // etc... 
     } 
}; 

在這種形式下,可以被稱爲f(x)任何函數對象將被接受。

+0

我應該在哪裏申報Functor?如果它有額外的參數,它會是什麼樣子? – BeeBand 2010-09-17 11:40:43

+0

@BeeBand:不需要聲明Functor,因爲它是一個模板參數。 – kennytm 2010-09-17 11:42:04

1

如果我理解它是正確的,那麼您在詢問函數是如何聲明的。這是一個小代碼,應該給你這個想法。

struct A{ 
void operator()(int x, double d){} // overloaded operator() 
}; 

int main(){ 
A a; 
a(2, 3.0); 
} 
相關問題