如何正确声明嵌套类?

时间:2013-09-30 03:37:20

标签: c++

以下代码是二进制树的实现,来自C ++数据结构文本。 我成功编译代码,得到一些错误消息。主要是,错误行来自最后两个代码。如何解决这个问题? 我的IDE是CODE :: BLOCK 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'

有许多错误消息,我选择其中一个来表示错误消息。

2 个答案:

答案 0 :(得分: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;}

答案 1 :(得分:1)

此:

class LinkedBinaryTree {
protected:
 struct Node;

被称为前向声明(Node)。它告诉编译器有一个带有 name 的类型,但它不是类的定义。除非其定义可见,否则无法创建类型的实例。前瞻性声明不是定义。

如果你写了:

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

然后您就可以创建Node

当您具有相关类型,或者您希望以特定方式订购声明时,嵌套类的前向声明通常很有用。

前向声明对于告诉编译器有一个具有该名称的类型是有用的,因此它可以在使用之前理解你的意图:

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

在这种情况下,指针不需要物理依赖,因此当它看到foo的声明时,名称足以满足编译器。

另请注意,您的前向声明在类的范围内声明NodePosition,因此编译器将其视为void preorder(Node* v,PositionList& pl)const;使用类的本地类型;例如void LinkedBinaryTree::preorder(LinkedBinaryTree::Node* v, LinkedBinaryTree::PositionList& pl)const;,而不是代码示例中全局命名空间中声明的PositionNode