Возвращаемый параметр не может быть принят в шаблоне c ++ - PullRequest
1 голос
/ 14 апреля 2011

Я пишу шаблон для двоичного дерева и не понимаю, почему я не могу вернуть Node * от одной из моих функций в этом шаблоне.

Код:

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;
    }
}

Есть мысли?

Спасибо.

Ответы [ 4 ]

5 голосов
/ 14 апреля 2011

Полностью укажите тип возвращаемого значения для функции поиска:

Binary_Tree<T>::Node* Binary_Tree<T>::find(T* dat, Node* current){ ...
1 голос
/ 14 апреля 2011

Похоже, вы пропустили два return: s в блоке if .. else if .. в find.

РЕДАКТИРОВАТЬ:

Код следующийпроблема в коде:

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);

Здесь вы просто завершаете функцию вызовом find.У вас есть для включения оператора return, например:

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);

Язык C не похож на lisp и ruby ​​,где последняя строка блока является неявным значением этого блока.

Тот факт, что это рекурсивный вызов, не делает вызов каким-либо образом особенным, в конце он простопростой вызов, и если вы планируете вернуть значение вызова, вы должны вернуть его явно.

1 голос
/ 14 апреля 2011

По определению, ваш узел является частным, так почему вы хотите вернуть в публичном методе частный тип?Более того, иногда компилятору трудно работать с шаблонами, иногда нужно сообщить им, является ли конкретная метка переменной или типом.Для этого вы можете использовать typename ключевое слово.

Кроме того, вы можете иметь свой класс узла вне Binary_Tree (проверено, оно компилируется):

 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;
     }
 }
0 голосов
/ 14 апреля 2011

В основном, когда вы пишете это:

template<class T> Node* Binary_Tree<T>::find(T* dat, Node* current){ 
...

как узнать, о каком Node* вы говорите?Вы должны явно сказать это.

Но есть другая, более глубокая проблема.То есть у вас есть открытые функции, возвращающие указатель на тип, который известен только внутренне (в частном порядке) классу.Что будет делать вызывающий find() с Node, который выходит.Ну, по твоему замыслу, единственное, что они могут сделать, это передать его обратно в один из открытых классов.Конкретнее, если вы ожидаете, что вызванная функция find() будет делать что-то вроде

p = tree.Find( /* some arguments */);

, тогда сделайте что-нибудь с p->left.Ну, это не должно компилироваться.

Возможное решение:

  • Переместить определение структуры с именем Node из класса в глобальную область видимости.(На самом деле, еще лучше, поместите его в пространство имен, потому что Node является таким распространенным именем.)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...