2013-09-30 2 views
0

Следующий код представляет собой реализацию двоичного дерева, исходя из текста структуры данных C++. Я не могу скомпилировать код успешно, получив некоторые сообщения об ошибках. В основном, строки ошибок исходят из двух последних кода. Как решить эту проблему? Моя IDE - КОД: БЛОК 12.11.Как правильно объявить вложенные классы?

#include<iostream> 
#include<list> 
using namespace std; 

typedef int Elem; 
struct Node 
{ 
Elem elt; 
Node *par; 
Node *left; 
Node *right; 
Node():elt(),par(NULL),left(NULL),right(NULL){} 
}; 

class Position 
{ 
private: 
Node *v; 
public: 
Position(Node *_v=NULL):v(_v){} 
Elem &operator*(){return v->elt;} 
Position left()const{return Position(v->left);} 
Position right()const{return Position(v->right);} 
Position parent()const{return Position(v->par);} 
bool isRoot()const{return v->par==NULL;} 
bool isExternal()const{return v->left==NULL&&v->right==NULL;} 
friend class LinkedBinaryTree; 
}; 
typedef std::list<Position> PositionList; 

class LinkedBinaryTree 
{ 
protected: 
struct Node; //This line is by me, the text merely tell you "insert Node declaration here. . ." I don't know whether this line is correct or not. 
public: 
class Position; // Also by me, the text merely tell you "insert Position declaration here. . ." I don't know wwhether this line is correct or not. 
public: 
LinkedBinaryTree(); 
int size()const; 
bool empty()const; 
Position root()const; 
PositionList positions()const; 
void addRoot(); 
void expandeExternal(const Position& p); 
protected: 
void preorder(Node* v,PositionList& pl)const; 
private: 
Node* _root; 
int n; 
}; 


LinkedBinaryTree::LinkedBinaryTree():_root(NULL),n(0){} 
int LinkedBinaryTree::size()const{return n;} 
bool LinkedBinaryTree::empty()const{return size()==0;} 
LinkedBinaryTree::Position LinkedBinaryTree::root()const{Position(_root);} //canot compile successfully, this error messages is : C:\Users\user\Documents\aa\main.cpp|58|error: return type 'class LinkedBinaryTree::Position' is incomplete 
void LinkedBinaryTree::addRoot(){_root=new Node;n=1;} //canoot compile successfully, this error message is C:\Users\user\Documents\aa\main.cpp|59|error: invalid use of incomplete type 'struct LinkedBinaryTree::Node' 

Существует много сообщений об ошибках, я выбираю один из них для представления сообщений об ошибках.

+0

прочитайте сообщения об ошибках, исправьте ошибки компиляции .... –

+1

Уменьшите количество строк в вашей программе, пока не получите наименьший набор, создающий проблему. Скорее всего, проблема будет смотреть на вас в лицо в то время. – Floris

+0

Code :: blocks - это IDE, а не компилятор. – harper

ответ

1

В этом:

class LinkedBinaryTree { 
protected: 
struct Node; 

называется опережающее объявление (о Node). Он сообщает компилятору, что есть тип с именем, но это не определение класса. Вы не можете создать экземпляр типа, если его определение не будет видимым. Передовая декларация не является определением.

Если бы вы написали:

class LinkedBinaryTree { 
protected: 
struct Node { /* ... */ }; 

Тогда вы могли бы создать Node.

Перспективное объявление вложенного класса обычно полезно, если у вас есть созависимые типы, или вы предпочитаете заказывать объявления определенным образом.

Переднее заявление полезно сообщить компилятору есть тип с этим именем, так что он может понять ваши намерения до его использования:

class LinkedBinaryTree { 
protected: 
struct Node; 
void foo(Node*); 
struct Node { /* ... */ }; 

В этом случае указатель не требует физической зависимости , поэтому имя достаточно, чтобы удовлетворить компилятор, когда он видит объявление foo.

Также обратите внимание, что ваше декларативное объявление объявляет Node и Position в области класса, поэтому компилятор считает, что void preorder(Node* v,PositionList& pl)const; использует типы, локальные для класса; например void LinkedBinaryTree::preorder(LinkedBinaryTree::Node* v, LinkedBinaryTree::PositionList& pl)const;, а не Position и Node, объявленных в глобальном пространстве имен в вашем примере кода.

1

Уплотненный декларация должна обычно происходить внутри класса, как это:

#include<iostream> 
#include<list> 
using namespace std; 

class LinkedBinaryTree 
{ 
    protected: 
    typedef int Elem; 
    struct Node 
    { 
    Elem elt; 
    Node *par; 
    Node *left; 
    Node *right; 
    Node():elt(),par(NULL),left(NULL),right(NULL){} 
    }; 

    public: 
    class Position 
    { 
    private: 
    Node *v; 
    public: 
    Position(Node *_v=NULL):v(_v){} 
    Elem &operator*(){return v->elt;} 
    Position left()const{return Position(v->left);} 
    Position right()const{return Position(v->right);} 
    Position parent()const{return Position(v->par);} 
    bool isRoot()const{return v->par==NULL;} 
    bool isExternal()const{return v->left==NULL&&v->right==NULL;} 
    friend class LinkedBinaryTree; 
    }; 
    typedef std::list<Position> PositionList; 
    public: 
    LinkedBinaryTree(); 
    int size()const; 
    bool empty()const; 
    Position root()const; 
    PositionList positions()const; 
    void addRoot(); 
    void expandeExternal(const Position& p); 
    protected: 
    void preorder(Node* v,PositionList& pl)const; 
    private: 
    Node* _root; 
    int n; 
}; 


LinkedBinaryTree::LinkedBinaryTree():_root(NULL),n(0){} 
int LinkedBinaryTree::size()const{return n;} 
bool LinkedBinaryTree::empty()const{return size()==0;} 
LinkedBinaryTree::Position LinkedBinaryTree::root()const{Position(_root);} //canot compile successfully, this error messages is : C:\Users\user\Documents\aa\main.cpp|58|error: return type 'class LinkedBinaryTree::Position' is incomplete 
void LinkedBinaryTree::addRoot(){_root=new Node;n=1;} 
+0

Это заявление работает. Спасибо. Почему я не могу объявить и определить их вне класса? – Makoto

+0

Весь смысл вложенных классов состоит в том, что они происходят в другом классе. Поэтому нет смысла определять их вне материнского класса. – user2829635

Смежные вопросы