C++:将函数作为参数传递给另一个函数

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

+1:希望原帖作者使用新的风格而不是C风格 :) - Matthieu M.
+1 - 也许值得添加一条说明这两种方法的优缺点的注释(函数对象可以存储状态,并且更容易被编译器内联)。 - jalf

2

是的,您可以将函数指针作为参数传递给in_order。如果传递的函数签名不匹配,则还需要进行重载。对于像print_node这样的函数,声明in_order应该像这样(假设其返回类型也为void):

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

2
我认为你应该使用访问者模式。

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

基础访问者类应该有一个虚方法来操作节点。将访问者作为参数传递给您的 in_order 方法。然后,根据您想要执行的任何操作,派生出尽可能多的访问者。

1
实际上,访问者模式可能比您想要实现的更强大。策略模式应该就足够了。http://en.wikipedia.org/wiki/Strategy_pattern - Julio
这并不完全是我想要的。我认为对于一个小型二叉树类来说,两者都太臃肿了。不过,这些概念很有趣! - Patrick Oscity
是的,可能会更加臃肿,但也许更加强大。而且当我使用C++时,我尽量避免使用静态函数。 - Julio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接