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

时间:2019-06-02 14:19:14

标签: c++ class c++11 templates member-function-pointers

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

binarySearchTree

这是有效的代码

"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)) print的声明与上面的声明在 .cpp 中)

binarySearchTree

错误是在void bst::printfunctions(classdatatype& x) { tree.inorderTraversal(print(classdatatype & x)); //error here } void bst::print(classdatatype& x) { cout << x << " "; } 中引起的,我已经尝试了许多不同的方法,但是对我来说,这是正确的声明。因此我不知道为什么它不起作用。

任何建议将不胜感激。


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


EDIT2 :最小的可复制示例。

数据类型保持不变,与上面的示例不同。这是我可以做到的最基本的操作,最终我得到了另一个我无法解决的错误,但就本示例而言,这无关紧要,应该忽略。 classdatatype已包含在内,但数量很少,可能无法达到目的,但问题仍然不在这里。

main()

main()

课程#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

1 个答案:

答案 0 :(得分:3)

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

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

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


OP在评论中提到,他/她希望将成员函数print()bst类传递给inorderTraversal()类的成员函数binarySearchTree<elemType>。在那种情况下,仅传递 member-function 是不够的,此外还应传递将调用print函数的类的实例 >。

通过捕获bst类的实例并传递给{{1}的inorderTraversal() Lambda 函数可以很方便地简化此过程}类。

这意味着在binarySearchTree内提供:

template <class elemType> 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

此处正在编译代码:https://godbolt.org/z/jhCnPs


PS :另一个错误是来自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 } 类的operator<<,您错过了返回windlogtype的引用的错误。

说实话,通过用std::ostream代替windlogtype并在声明旁边显示成员函数的定义,您可以制作出更简单的最小代码。这将使代码易于阅读。