2009-11-04 7 views
4

je suis exécute actuellement un arbre binaire en C++ et je veux traverser avec une fonction appelée in_order().C++: la fonction passe en tant que paramètre à une autre fonction

est-il possible de passer une fonction comme argument, afin que je puisse faire des choses comme ci-dessous (sans avoir à écrire le code pour parcourir la liste plus d'une fois)?

struct tree_node; // and so on 
class tree;  // and so on 

void print_node() { 
    // some stuff here 
} 

// some other functions 

tree mytree(); 

// insert some nodes 

mytree.in_order(print_node); 
mytree.in_order(push_node_to_stack); 
mytree.in_order(something_else); 

Répondre

14

Oui, vous pouvez le faire de plusieurs façons. Voici deux possibilités communes.

pointeurs de fonction de style ancien

class mytree 
{ 
    // typedef for a function pointer to act 
    typedef void (*node_fn_ptr)(tree_node&); 

    void in_order(node_fn_ptr) 
    { 
     tree_node* pNode; 

     while (/* ... */) 
     { 
     // traverse... 
     // ... lots of code 

     // found node! 
      (*fnptr)(*pNode); 
      // equivalently: fnptr(*pNode) 
     } 
    } 
}; 

void MyFunc(tree_node& tn) 
{ 
    // ... 
} 

void sample(mytree& tree) 
{ 
    // called with a default constructed function: 
    tree.inorder(&MyFunc); 
    // equivalently: tree.inorder(MyFunc); 
} 

En utilisant foncteurs

Avec un membre de modèle, fonctionne avec des pointeurs de fonction

class mytree 
{ 
    // typedef for a function pointer to act 
    typedef void (*node_fn_ptr)(tree_node&); 

    template<class F> 
    void in_order(F f) 
    { 
     tree_node* pNode; 

     while (/* ... */) 
     { 
     // traverse... 
     // ... lots of code 

     // found node! 
      f(*pNode); 
     } 
    } 
}; 

struct ExampleFunctor 
{ 
    void operator()(tree_node& node) 
    { 
     // do something with node 
    } 
} 

void sample(mytree& tree) 
{ 
    // called with a default constructed function: 
    tree.inorder(ExampleFunctor()); 
} 
+0

+1 Vous me battez par 30s;) – AraK

+1

@AraK: Je tapais aussi vite que je pouvais ... –

+0

merci, m'a vraiment beaucoup aidé! –

1

Oui, vous pouvez utiliser un pointeur de fonction en tant que paramètre à in_order. Vous pouvez également avoir besoin de le surcharger, au cas où les signatures des fonctions passées ne correspondent pas. Pour les fonctions comme print_node, déclarent in_order comme celui-ci (à condition que son type de retour est void aussi bien):

void tree::in_order(void (*)()) 
{ 
    //implementation 
} 
1

Je pense que vous devriez utiliser le modèle des visiteurs à la place.

http://en.wikipedia.org/wiki/Visitor_pattern

La classe des visiteurs de base devrait avoir une méthode virtuelle pour fonctionner sur un nœud. Passez le visiteur en argument à votre méthode in_order. Puis dérivez votre visiteur autant de fois que vous le souhaitez pour toute opération que vous voulez faire.

+1

En fait, le modèle de visiteur est probablement plus puissant que ce que vous voulez vraiment atteindre. Le modèle de stratégie devrait suffire. http://en.wikipedia.org/wiki/Strategy_pattern – Julio

+0

il est à la fois pas tout à fait ce que je cherchais. Je pense que les deux seraient trop gonflés pour une petite classe d'arbre binaire. concepts intéressants, cependant! –

+0

Ouais un peu plus gonflé, mais probablement plus puissant. Et quand je travaille en C++ j'essaie d'éviter à toutes les fonctions statiques de coûts. – Julio