5

我目前正在用 C++ 实现一棵二叉树,我想用一个名为 in_order() 的函数来遍历它。

有什么方法可以将函数作为参数传递,以便我可以执行以下操作(无需编写代码来多次遍历列表)?

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

3 回答 3

15

是的,您可以通过多种方式做到这一点。这里有两种常见的可能性。

旧式函数指针

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

使用函子

使用模板成员,使用函数指针

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());
}
于 2009-11-04T12:01:33.580 回答
2

是的,您可以使用函数指针作为in_order. 您可能还需要重载它,以防传递的函数的签名不匹配。对于像这样的函数print_node,像这样声明 in_order (假设它的返回类型也是void如此):

void tree::in_order( void (*)() )
{
   //implementation
}
于 2009-11-04T12:03:16.287 回答
2

我认为您应该改用访问者模式。

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

访问者基类应该有一个在节点上操作的虚方法。将访问者作为参数传递给您的 in_order 方法。然后为您想要执行的任何操作多次导出您的访问者。

于 2009-11-04T13:11:36.753 回答