传递模板类的成员函数指针及static成员函数

在阅读《C++数据结构与算法》时,作者尝试将一个成员函数指针作为参数传递给二叉查找树的遍历方法。遇到编译错误C2440,提示无法将成员函数指针转换为全局函数指针。经过思考发现,由于在类未实例化时不能使用非静态成员函数,因此必须使用static成员函数。添加static关键字后,代码成功编译通过。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前几天相中并买下了一本《C++数据结构与算法》,的确是相中了,封面看起来B格就很高,今天把它拿出来抖抖灰,敲了书上P175的一段二叉查找树的代码。突发奇想给遍历成员函数传递一个函数成员指针,用来访问节点数据,并在类内定义成员函数vist,作为默认的访问函数,如下面的BFS遍历,

template <typename T>
void BST<T>::breadthFirst(void(*func)(BSTNode<T> *) = &BST<T>::vist)
{
	std::queue<BSTNode<T> *> que;
	BSTNode<T> *p = root;
	if (p == 0)
		return;
	que.push(p);
	while (!que.empty())
	{
		p = que.front();
		que.pop();	
		if (p->left)
			que.push(p->left);
		if (p->right)
			que.push(p->right);
		func(p);
	}
}
//BST::vist
template <typename T>
inline void BST<T>::vist(BSTNode<T> *node)
{
	cout << node->val << ' ';
	return;
}
结果编译时报错:

错误 1 error C2440: “默认参数”: 无法从“void (__thiscall BST<int>::* )(BSTNode<T> *)”转换为“void (__cdecl *)(BSTNode<T> *)”

话说以前并没有见到过类似报错,在捣鼓了老半天之后,一拍脑门想到:thiscall 和cdecl,是不是少一个static关键字? 加上!果然就喜闻乐见的编译通过了!


//定义不变,类内的声明加上static关键字
static void vist(BSTNode<T> *);
在网上找了一下,看到这个帖子

http://bbs.youkuaiyun.com/topics/390246787

1、类没有实例化前,只能用静态成员函数操作

显然在传递成员函数指针时,并没有实例化的类,所以必须是static成员函数

源代码:

<p>
</p><pre name="code" class="cpp">/* main.cpp */
#include "genBST.h"
#include <stdlib.h>
#include <time.h>
using namespace std;
int main()
{
	BST<int> bst;
	srand((unsigned int)time(NULL));
	for (int i = 0; i < 20; ++i)
	{
		int temp = rand() % 100;
		bst.insert(temp);
	}
	bst.inorder();
	std::cout << endl;
	bst.preorder();
	cout << endl;
	bst.postorder();
	cout << endl;
	bst.breadthFirst();
	cout << endl;
	int n;
	//while (cin >> n)
	//{
	//	BSTNode<int> * p=bst.search(n);
	//	if (p)
	//		cout << p << ' ';
	//}
	return 0;
}

/* genBST.H */
#include <iostream>
#include <string>
#include <queue>
template<typename T>
class BSTNode
{
public:
	BSTNode(){
		left = right = 0;
	}
	BSTNode(const T &v, BSTNode<T> *l = 0, BSTNode<T> *r = 0)
	{
		val = v;
		left = l;
		right = r;
	}
	T val;
	BSTNode<T> *left, *right;
};
template <typename T>
class BST
{
private:
	BSTNode<T> * root;
	void clear();
	BSTNode<T> *search(BSTNode<T> *, const T &) const;
	void preorder(BSTNode<T> *, void(*func)(BSTNode<T> *));
	void inorder(BSTNode<T> *, void(*func)(BSTNode<T> *) );
	void postorder(BSTNode<T> *, void(*func)(BSTNode<T> *));
public:
	BST()
	{
		root = 0;
	}
	~BST()
	{
		clear();
	}

	bool empty() const
	{
		return root == 0;
	}
	void preorder(void(*func)(BSTNode<T> *) = &BST<T>::vist)
	{
		preorder(root,func);
	}
	void inorder(void(*func)(BSTNode<T> *) = &BST<T>::vist)
	{
		inorder(root,func);
	}
	void postorder(void(*func)(BSTNode<T> *) = &BST<T>::vist)
	{
		postorder(root,func);
	}
	BSTNode<T> * search(const T &v) const
	{
		return search(root, v);
	}
	static void vist(BSTNode<T> *);
	static void del(BSTNode<T> *);
	void breadthFirst(void(*func)(BSTNode<T> *) = &BST<T>::vist);
	void insert(const T &);
};
template <typename T>
BSTNode<T> * BST<T>::search(BSTNode<T> *root, const T &v) const
{
	
	BSTNode<T> *p = root;
	while (p)
	{
		if (p->val == v)
			break;
		else if (p->val > v)
			p = p->left;
		else
			p = p->right;
	}
	return p;
}
template <typename T>
void BST<T>::breadthFirst(void(*func)(BSTNode<T> *) = &BST<T>::vist)
{
	std::queue<BSTNode<T> *> que;
	BSTNode<T> *p = root;
	if (p == 0)
		return;
	que.push(p);
	while (!que.empty())
	{
		p = que.front();
		que.pop();	
		if (p->left)
			que.push(p->left);
		if (p->right)
			que.push(p->right);
		func(p);
	}
}
template <typename T>
void BST<T>::preorder(BSTNode<T> *root, void(*func)(BSTNode<T> *))
{
	BSTNode<T> *p = root;
	if (p)
	{
		func(p);
		if (p->left)
			preorder(p->left,func);
		if (p->right)
			preorder(p->right,func);
	}
}
template <typename T>
void BST<T>::inorder(BSTNode<T> *root, void(*func)(BSTNode<T> *))
{
	BSTNode<T> * p = root;
	if (p)
	{
		if (p->left)
			inorder(p->left, func);
		func(p);
		if (p->right)
			inorder(p->right, func);
	}
}
template <typename T>
void BST<T>::postorder(BSTNode<T> *root, void(*func)(BSTNode<T> *))
{
	BSTNode<T> *p = root;
	if (p)
	{
		if (p->left)
			postorder(p->left, func);
		if(p->right)
			postorder(p->right, func);
		func(p);
	}
}
template <typename T>
void BST<T>::insert(const T &v)
{
	if (!root)
	{
		root = new BSTNode<T>(v);
		return;
	}
	BSTNode<T> *p = root;
	while (1)
	{
		if (p->val == v)
			return;
		else if (p->val > v)
		{
			if (!p->left)
			{
				p->left = new BSTNode<T>(v);
				return;
			}
			p = p->left;
		}
		else
		{
			if (!p->right)
			{
				p->right = new BSTNode<T>(v);
				return;
			}
			p = p->right;
		}
	}
}
template <typename T>
inline void BST<T>::vist(BSTNode<T> *node)
{
	cout << node->val << ' ';
	return;
}
template <typename T>
void BST<T>::del(BSTNode<T> *root)
{
	delete root;
	root = 0;
}
template <typename T>
void BST<T>::clear()
{
	breadthFirst(&BST<T>::del);
	root = 0;
}
</pre>



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值