I am writing a template for binary tree and don't understand why I can't return Node* from one of my functions in that template.
Code:
template<class T>
class Binary_Tree{
private:
struct Node{
T* data;
Node *left,*right;
Node(T* dat, Node* l, Node* r) : data(dat),left(l=0),right(r=0) {}
}*root;
public:
Binary_Tree() : root(0) {}
Node* find(T* dat);
....
};
template<class T>
Node* Binary_Tree<T>::find(T* dat, Node* current){
if (*current->data == *dat){
return current;
}else if(*current->data < *开发者_高级运维dat && current->left == 0){
return current;
}else if(*current->data > *dat && current->right == 0){
return current;
}else if (*current->data < *dat){
find(dat,current->left);
}else if(*current->data > *dat){
find(dat,current->right);
}else{
return 0;
}
}
Any thoughts?
Thanks.
Fully qualify the return type to your find function:
Binary_Tree<T>::Node* Binary_Tree<T>::find(T* dat, Node* current){ ...
By definition, your node is private, so why would you want to return in a public method a private type ? Moreover, sometime, compiler have hard time with templates, sometime, you need to let them know if a specific label is a variable or a type. You can use typename key word for that.
Additionally, you can have your node class outside of the Binary_Tree (checked, it does compile):
template<class T>
class Node {
T* data;
Node<T> *left,*right;
Node<T> (T* dat, Node<T> * l, Node<T> * r) : data(dat),left(l=0),right(r=0) {}
};
template<class T>
class Binary_Tree{
private:
Node<T> *root;
public:
Binary_Tree() : root(0) {}
Node<T>* find(T* dat,Node<T> *); // changed prototype
};
template<class T>
Node<T>* Binary_Tree<T>::find(T* dat, Node<T>* current){
if (*current->data == *dat){
return current;
}else if(*current->data < *dat && current->left == 0){
return current;
}else if(*current->data > *dat && current->right == 0){
return current;
}else if (*current->data < *dat){
return find(dat,current->left); // add missing return
}else if(*current->data > *dat){
return find(dat,current->right); // add missing return
}else{
return 0;
}
}
It looks like you've missed two return
:s in the if .. else if ..
block in find
.
EDIT:
The code following code is the problem:
template<class T>
Node* Binary_Tree<T>::find(T* dat, Node* current){
if (...) {
..
} else if (*current->data < *dat){
find(dat,current->left);
}else if(*current->data > *dat){
find(dat,current->right);
Here, you simply end the function with a call to find
. You have to include the return
statement, as in:
template<class T>
Node* Binary_Tree<T>::find(T* dat, Node* current){
if (...) {
..
} else if (*current->data < *dat){
return find(dat,current->left);
}else if(*current->data > *dat){
return find(dat,current->right);
The C language is not like lisp and ruby, where the last line of a block is the implicit value of that block.
The fact that this is a recursive call does not make the call special in any way, it the end it's just a plain call, and if you plan to return the value of the call you have to return it explicitly.
Basically, when you write this:
template<class T> Node* Binary_Tree<T>::find(T* dat, Node* current){
...
how is it supposed to know which Node*
you are talking about? You have to explicitly tell it.
But there's another, deeper issue. That is, you have a public functions returning a pointer to a type that is only known internally (privately) to the class. What is the caller of find()
going to do with the Node
that comes out. Well by your design, the only that they can do it pass it back into one of the classes public members. More concretely, if you expect the called of the find()
function to do something like
p = tree.Find( /* some arguments */);
then do something with p->left
. Well this shouldn't compile.
A possible solution:
- Move the definition of the struct called
Node
out of the class and into the global scope. (Actually, better yet, put it in a namespace, becauseNode
is such a common name.)
精彩评论