前几天相中并买下了一本《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>