2010-04-22 135 views
1

我遇到一些问题,使用模板和继承将代码分解为可重用部分。我想实现我的树类和avltree类使用相同的节点类,并且avltree类从树类继承了一些方法并添加了一些特定的方法。所以我想出了下面的代码。编译器会在下面标记的tree.h中引发一个错误,我不知道如何解决这个问题。任何帮助感谢! :)C++模板和继承

node.h:

#ifndef NODE_H 
#define NODE_H 
#include "tree.h" 

template <class T> 
class node 
{ 
T data; 
    ... 

node() 
    ... 

    friend class tree<T>; 
}; 

#endif 

tree.h中

#ifndef DREVO_H 
#define DREVO_H 

#include "node.h" 

template <class T> 
class tree 
{ 
public: //signatures 
    tree(); 
... 

    void insert(const T&); 
private: 
    node<T> *root; //missing type specifier - int assumed. Note: C++ does not support default-int 


}; 
//implementations 

#endif 

avl.h

#ifndef AVL_H 
#define AVL_H 

#include "tree.h" 
#include "node.h" 

template <class T> 
class avl: public tree<T> 
{ 
public: //specific 
    int findMin() const; 
... 

protected: 
    void rotateLeft(node<T> *)const; 
private: 
    node<T> *root; 

}; 

#endif 

avl.cpp(我试过实现分离头,它的工作在我开始将avl码与树码结合之前)

#include "drevo" 
#include "avl.h" 
#include "vozlisce.h" 

template class avl<int>; //I know that only avl with int can be used like this, but currently this is doesn't matter :) 
//implementations 
... 

回答

8

tree.hnode.h都试图包括对方,包括警卫将阻止他们之一看到其他人。

而不是#include "tree.h"尽量向前声明树,如:

template <class T> 
class tree; 

node.h

编辑:作为SBI的评论所说,它更有意义转发声明treenode.h比其他因为它是通过friend声明授予tree访问node

+0

我认为在''node.h“'中'#include”tree.h“'会比其他方式更有意义。毕竟,很难想象如何实现一个没有节点的树,而对于'friend'声明,'tree'的前向声明就足够了。 – sbi 2010-04-22 11:24:24

+0

@sbi你当然是对的 – 2010-04-22 11:29:28

+0

递归包括是如此有趣...你知道任何预处理器警告这些野兽吗?我的意思是可以写'#ifdef HEADER_GUARD \ n #error“HEADER_GUARD定义了”\ n#else'而不是'#ifndef',但它已经非常杂乱了...... – 2010-04-22 11:37:54

2

不要在“node.h”中包含“tree.h”。

此外,您在treeavl类中都声明了root。将tree::root限定为protected并删除avl::root

0

问题是因为tree.h和node.h之间的头文件的循环依赖。由于node.h包含tree.h,因此在编译树类时,编译器不知道节点的类型是什么。由于您只是为了宣告朋友而使用它,因此无需在node.h中包含头文件tree.h

1

您的问题是tree.h包含node.h,反之亦然。我不会认为节点必须知道树或给它友谊是必要的(或者说是有道理的),所以我会删除它。