如何在类中将函数作为参数传递?

Posted

技术标签:

【中文标题】如何在类中将函数作为参数传递?【英文标题】:How to pass functions as parameters within a class? 【发布时间】:2019-06-02 14:19:14 【问题描述】:

我试图通过我的inordertraversal 类将我的print 函数作为参数传递,该类属于模板化binarySearchTree。每当我在 main 中定义这些函数时,程序都可以正常工作,但是每当我尝试封装它们时,都会出现错误:

"expected primary-expression before '&' token"

这是有效的代码

void print(classdatatype& x); 
int main()

    binarySearchTree<classdatatype> tree;
    tree.inorderTraversal(print);
    return 0;


void print(classdatatype& x)     cout << x << " ";       

我的inordertraveral模板类的声明是

template <class elemType>
void binarySearchTree<elemType>::inorderTraversal(void (*visit)(elemType& item))

如果需要,我可以显示其余代码,但这一切都很好

一旦我将这些函数移到我的类中,它看起来像这样 (printbinarySearchTree 的声明在 .cpp 中与上面声明的相同)

void bst::printfunctions(classdatatype& x)

    tree.inorderTraversal(print(classdatatype & x)); //error here


void bst::print(classdatatype& x) 
 
    cout << x << " "; 
 

错误是在print的括号内做,我尝试了很多不同的东西,但对我来说这是正确的声明;因此我不知道为什么它不起作用。

任何建议将不胜感激。


编辑print 是一个函数指针,用于打印存储在二叉搜索树中的classdatatype 的详细信息。


EDIT2:最小的可重现示例。

数据类型与上面的示例相同,但与上面的示例不同。这是我可以做到的最基本的,我最终得到了另一个我无法解决的错误,但对于这个例子来说,它并不重要,应该被忽略。 main() 包含在内,但很小,可能无法达到其目的,但问题不在于这里。

ma​​in()

#include <iostream>
#include "windlogtype.h"
using namespace std;

int main()

    windlogtype wind;

    ifstream infile("data.txt");
    //for purose of this data is one integer value
    infile >> wind;

    //do something
    //main purpose is to get input
    return 0;

班级windlogtype

#include "windlogtype.h"
windlogtype::windlogtype()      
windlogtype::windlogtype(int i)        num = i;     
int windlogtype::Getnumber() const     return num;     
void windlogtype::Setnumber(int i)     num = i;     
ostream operator<<(ostream& os, const windlogtype& w)

    os << w.Getnumber() << '\n';
    return os;


#ifndef WINDLOGTYPE_H
#define WINDLOGTYPE_H

#include <iostream>
using namespace std;

class windlogtype

public:
    windlogtype();
    windlogtype(int i);
    int Getnumber() const;
    void Setnumber(int i);
private:
    int num;
;
ostream operator<<(ostream& os, const windlogtype& w);

#endif // WINDLOGTYPE_H

班级binarySearchTree

#include <iostream>
#include <assert.h>
using namespace std;

template <class elemType> struct binaryTreeNode

    elemType info;
    binaryTreeNode<elemType>* llink;
    binaryTreeNode<elemType>* rlink;
;

template <class elemType> class binarySearchTree

public:
    const binarySearchTree<elemType>& operator=(const binarySearchTree<elemType>&);
    void inorderTraversal(void (*visit) (elemType&));
    binarySearchTree();
    ~binarySearchTree();
    binaryTreeNode<elemType>* root;
private:
    void inorder(binaryTreeNode<elemType>* p, void (*visit) (elemType&));
;

template <class elemType> binarySearchTree<elemType>::binarySearchTree() 
    root = NULL;
    
template <class elemType> void binarySearchTree<elemType>::inorderTraversal(void (*visit) (elemType& item))

    inorder(root, *visit);
    
template <class elemType> void binarySearchTree<elemType>::inorder(binaryTreeNode<elemType>* p, void (*visit) (elemType& item))

    if (p != NULL)
    
        inorder(p->llink, *visit);
        (*visit)(p->info);
        inorder(p->rlink, *visit);
    

班级bst

#ifndef BST_H
#define BST_H
#include "binarySearchTree.h"
#include "windlogtype.h"
using namespace std;

class bst

public:
    bst();
    void InsertTree(windlogtype& newwind);
    void printfunctions(windlogtype& x);
    binarySearchTree<windlogtype>& GetTree();
    void print(windlogtype& x);
private:
    binarySearchTree<windlogtype> treeRoot;
;    
#endif // BST_H

#include "bst.h"

bst::bst()/*ctor*/     
binarySearchTree<windlogtype>& bst::GetTree()      return treeRoot;  
void bst::print(windlogtype& x)                    cout << x << " ";  
void bst::printfunctions(windlogtype& x)

    treeRoot.inorderTraversal(print(windlogtype & x)); // error lies here

【问题讨论】:

有什么理由不使用std::function 作为参数类型? 我对 c++ 很陌生,我不确定 std::function 是什么或如何使用它。 en.cppreference.com/w/cpp/utility/functional/function 当你把这个函数移到你的类中时,你把它改成static了吗?如果您提供minimal reproducible example 会更好。 只是为了澄清:你是否试图将 printbst 类传递给 inorderTraversalbinarySearchTree&lt;elemType&gt; 类? 【参考方案1】:

void bst::print(classdatatype& x) // is a member function

void print(classdatatype& x);    // is a free function.

因此function pointers to hold them 也会有所不同。


OP 在 cmets 中提到,他/她想将成员函数 print()bst 类传递给 binarySearchTree&lt;elemType&gt; 类的成员函数inorderTraversal()。在那种情况下传递成员函数是不够的,此外还应该传递print函数将被调用到的类的实例

Lambda 函数可以通过捕获bst 类的实例并传递给binarySearchTree 类的inorderTraversal() 来方便地简化此操作。

也就是说,在template &lt;class elemType&gt; class binarySearchTree 内部提供:

template<typename Callable>
void inorderTraversal(Callable visit)

    inorder(root, visit);  // simply pass visit further
    // or avoid coping by warapping std::cref(): i.e. inorder(root, std::cref(visit));


template<typename Callable>
void inorder(binaryTreeNode<elemType>* p, Callable visit)

    if (p != NULL)
    
        inorder(p->llink, visit);  // or inorder(root, std::cref(visit));
        visit(p->info);            // call directly with parameter
        inorder(p->rlink, visit);  // or inorder(root, std::cref(visit));
    

bst 类内部

void printfunctions(windlogtype& x)

    // lambda captures the instance by copy
    const auto printThisLogType = [this](windlogtype & x)->void  this->print(x); ;
    treeRoot.inorderTraversal(printThisLogType); // pass the callable lambda

这里是编译代码:https://godbolt.org/z/jhCnPs


PS:另一个错误来自windlogtype 类的operator&lt;&lt;,您错过了返回std::ostream 的引用。

老实说,您可以通过将windlogtype 替换为int 并在声明旁边显示成员函数的定义来制作更简单的最小代码。这将使代码易于阅读。

【讨论】:

以上是关于如何在类中将函数作为参数传递?的主要内容,如果未能解决你的问题,请参考以下文章

如何在用户定义的函数中将数据库列作为参数传递?

如何在 Maxima 中将列表作为变量参数函数传递?

如何在 C# 函数中将 jquery 变量作为参数传递

如何在python中将字典项作为函数参数传递? [复制]

如何在 Dart 中将 Navigator 函数作为参数传递?

如何在C中将函数指针数组的函数指针作为函数参数传递?