2010-04-22 113 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,反之亦然。我不會認爲節點必須知道樹或給它友誼是必要的(或者說是有道理的),所以我會刪除它。