如果我编写一个函数指针以在 BST 模板中使用,他们可以接受 1 个以上的对象作为参数吗?

If I write a function pointer to use in BST template, can they take more than 1 object as argument?

提问人:Emil Lang 提问时间:8/5/2022 最后编辑:wohlstadEmil Lang 更新时间:8/5/2022 访问量:102

问:

我为二叉搜索树写了一个模板。我希望重载按顺序遍历函数。当函数指针只接受类 T 的 1 个对象时,我可以让它工作。我希望它使用一个也使用 2 个整数值的函数指针,这样我就可以从 main 中的语句外部提取整数,然后我的函数指针将使用这些值在我的 BST 中查找对象。这可能吗?我将在下面展示我的代码。

例如,下面是一个仅使用对象的典型实现:T

template<class T>
void BSTTemplate<T>::inOrder(Node<T>* p) const
{
    if (p != nullptr)
    {
        inOrder(p->leftLink);
        cout << p->info << " ";
        inOrder(p->rightLink);
    }
}

template<class T>
void BSTTemplate<T>::inOrderTraversal() const
{
    inOrder(root);
}

当我激活它时,我的程序会按顺序吐出 BST 中的所有节点。

下面是相同的代码,但带有函数指针:

template<class T>
void BSTTemplate<T>::inOrder(Node<T>* p, void (*visit) (T&)) const
{
    if (p != nullptr)
    {
        inOrder(p->leftLink, *visit);
        (*visit) (p->info);
        inOrder(p->rightLink, *visit);
    }
}

template<class T>
void BSTTemplate<T>::inOrderTraversal(void (*visit) (T&)) const
{
    inOrder(root, *visit);
}

现在,在我的 I 中,我可以运行一个语句,例如:main()

//assume tree exists
Tree.inOrderTraversal(MyFunction);

其中 是一个 void 函数,使得MyFunction

void MyFunction(MyObject& myObj)
{

    //does something
}

我的目标是我想在我的树中使用一个函数,以便它从“外部”接收 2 个整数。(基本上是用户输入)

我尝试过这样的事情:

//overloading inOrder
template<class T>
void BSTTemplate<T>::inOrder(Node<T>* p, void (*visit) (T&,int&,int&)) const
{
    if (p != nullptr)
    {
        inOrder(p->leftLink, *visit);
        (*visit) (p->info);
        inOrder(p->rightLink, *visit);
    }
}

template<class T>
void BSTTemplate<T>::inOrderWithInputs(void (*visit) (T&,int&,int&)) const
{
    inOrder(root, *visit);
}

但是当我尝试像这样调用遍历函数时:main()

Tree.inOrderWithInputs(MyFunction(*arguments*));

解析器需要 类型为 、 an 和 another 的对象的参数。以前,当函数只有 void MyFunction(MyObject& myObj) 时,我只需要使用函数名称作为参数。由于自身有多个参数,我没有一个对象来填充它。TintintMyFunction

理想情况下,我想做一些类似的事情

Tree.inOrderTraversal(MyFunction(input1,input2));

其中输入是从用户处获取的整数。然后,该函数操作这些值以创建键,然后使用该键按顺序搜索树。

请帮我把这些点连接起来?

C++ 模板 binary-search-tree 函数指针 tree-traversal

评论

0赞 Sam Varshavchik 8/5/2022
你知道什么是,以及如何使用它吗?如果你这样做:在这里使用它有什么不清楚的地方?如果你不这样做,你会在你的C++教科书中找到完整的解释,有必要先了解类型擦除和。std::functionstd::function

答:

1赞 wohlstad 8/5/2022 #1

在 C++ 中,最好使用 std::function 而不是旧样式的函数指针。 是通过指定返回值和参数(根据需要任意数量)来实例化的模板。std::function

它支持传递您在代码中使用的全局函数以及 lambda(您也可以将类方法与 std::bind 一起使用)。

调用时,应将函数的参数作为附加参数提供(而不是使用实际调用函数并传递其返回值之类的参数)。inOrderTraversalMyFunction(input1,input2)

查看完整示例:

#include <functional>
#include <iostream>


template <typename T>
class BSTTemplate
{
public:
    //---------------------vvvvvvvvvvvvv---------------------------- 
    void inOrderWithInputs(std::function<void(T&, int&, int&)> visit,
                           T& arg1, int& arg2, int& arg3) const  // <--- the arguments for invoking the function
    {
        // Invoke the function with the arguments:
        visit(arg1, arg2, arg3);
    }
};


void GlobalFunc(float& arg1, int& arg2, int& arg3)
{
    std::cout << "exceuting GlobalFunc with args: " << arg1 << ", " << arg2 << ", " << arg3 << std::endl;
}


int main() 
{
    BSTTemplate<float> bst;
    float f{ 0 };
    int i1{ 1 };
    int i2{ 2 };

    // Call with a global function:
    bst.inOrderWithInputs(GlobalFunc,
                          f, i1, i2);   // <--- the arguments for invoking the function

    // Call with a lambda:
    bst.inOrderWithInputs([](float& arg1, int& arg2, int& arg3) 
                          { std::cout << "exceuting lambda with args: " << arg1 << ", " << arg2 << ", " << arg3 << std::endl; },
                          f, i1, i2);   // <--- the arguments for invoking the function

    return 0;
}

输出:

exceuting GlobalFunc with args: 0, 1, 2
exceuting lambda with args: 0, 1, 2

评论

0赞 Goswin von Brederlow 8/7/2022
或者仅用于隐式模板。auto fn