2010-07-06 79 views
3

在瘋狂的時刻,我決定編寫一個四叉樹C++模板類。我遇到了一些奇怪的編譯器錯誤,我不明白關於子類和指向模板的指針。我已經發現了一些哈克變通,但我想知道如果有人能闡明爲什麼我的代碼將無法編譯一些光...模板子類指針問題


我在Linux上,與scons的建設,使用G ++

我的代碼看起來是這樣的,我有一個模板類來描述樹和描述「葉子」的子類:

template <class value_type> 
class QuadTree 
{ 

public: 

    class Leaf //-Subclass-------------------------- 
    { 
     friend class QuadTree<value_type>; 
    protected: 
     value_type* m_data; 

     Leaf(); 
     ~Leaf(); 

    }; //-end-subclass------------------------------ 

    QuadTree(); 

    ~QuadTree(); 

    Leaf * Insert (const value_type & _x); 

protected: 

    QuadTree(Quadtree<value_type>* _parent); 

    QuadTree<value_type>* m_parent; 

    QuadTree<value_type>* m_children[4]; 

    std::set< Leaf* > m_leaves; 

}; 

首先指針問題,我得到的是四叉樹的析構函數:

template <class value_type> 
QuadTree<value_type>::~QuadTree() 
{ 
    // ... Delete children ... 

    // I allocate each leaf, so I need to delete them 
    std::set< Leaf* >::iterator it = m_leaves.begin(); // <-- bad 
    std::set< Leaf* >::iterator endit = m_leaves.end(); // <-- bad 
    for(;it != endit; ++it) 
     delete *it; 
} 

當我編譯時,我得到這個錯誤:expected ';' before ‘it’expected ';' before ‘endit’。 其他指針錯誤是在插入函數定義:

template <class value_type> 
Leaf * QuadTree<value_type>::Insert (const value_type & _x) // <-- bad 
{ 
    // Insert stuff... 
} 

我得到的編譯錯誤:expected constructor, destructor, or type conversion before ‘*’ token

誰知道爲什麼我得到這些錯誤?我已經修復了這些問題,但我想知道爲什麼我不能這樣做。

詩篇。我編輯過的代碼在這裏顯示,所以我可能錯過了一些我認爲完全不相干的東西。

編輯。修正了四叉樹 - >四叉樹錯字

+1

你在QuadTree與Quadtree – sje397 2010-07-06 11:15:03

+0

中遇到了一些情況,修復了QuadTree錯字,這不是我原來的代碼。 – m0tive 2010-07-06 11:21:39

回答

4

你需要

typename std::set< Leaf* >::iterator it = m_leaves.begin(); 
typename std::set< Leaf* >::iterator endit = m_leaves.end(); 

類型的std ::的集依賴於另一個模板參數,你必須告訴編譯器,這實際上是一種類型。 gcc 4.5.0會產生更好的錯誤信息。

第二誤差是相似的:

template <class value_type> 
typename QuadTree<value_type>::Leaf* QuadTree<value_type>::Insert (const value_type & _x) 
{ 
    // Insert stuff... 
} 

葉是一個內部類四叉樹。你需要命名它,你需要指定QuadTree的類型,因爲內部類取決於模板參數。

另一件事:你在許多地方都有QuadTree的拼寫錯誤。

+0

謝謝,雖然我不確定你最近的評論意味着什麼/關於... – m0tive 2010-07-06 11:17:14

+0

你發佈的示例代碼使用「Quadtree」或「QuadTree」。注意小寫字母t?哦,我只注意到我的錯字。謝謝,弗雷德。這令人困惑......我看到了錯字,按下了編輯,它已經消失,被壓回來了,它再次出現,刷新了頁面,意識到了。 – pmr 2010-07-06 11:19:00

+0

@ m0tive:我編輯了帖子,現在應該有道理;-) – fredoverflow 2010-07-06 11:19:27

1

您需要typename關鍵字糾正第一個問題,如:

typename std::set< Leaf* >::iterator it = m_leaves.begin(); 

的第二個問題是由事實Leafvalue_type不命名類型在該行造成。你需要指定你的意思LeafQuadtree<value_type>value_type,如:

template <class value_type> 
Quadtree<value_type>::Leaf * Quadtree<value_type>::Insert (const typename Quadtree<value_type>::value_type & _x) 
1

在你需要告訴編譯器std::set< Leaf* >::iterator第一種情況是類型:

typename std::set< Leaf* >::iterator it = ... 
typename std::set< Leaf* >::iterator endit = ... 

由於Leaf取決於(間接)的模板參數,編譯器現在不能肯定什麼確切類Leaf會結果是,並且不知道std::set<Leaf*>是否會有專門化,以及這些專業化如何定義iterator。因此編譯器假定iterator是一個正常的成員變量std::set< Leaf* >,除非typename關鍵字另有說明。

第二個問題是,當你指定返回值Leaf時,你還沒有進入你的類範圍,編譯器不知道你指的是嵌套類。改爲使用該類的完全限定名稱:

template <class value_type> 
typename Quadtree<value_type>::Leaf * Quadtree<value_type>::Insert (...) ... 
1

無關......但仍然。

Leaf類是你不應該做的一個例子。

class Leaf //-Subclass-------------------------- 
{ 
    friend class QuadTree<value_type>; 
protected: 
    value_type* m_data; 

    Leaf(); 
    ~Leaf(); 

}; //-end-subclass------------------------------ 
  • 不使用protected的屬性,它是與使用public。這意味着你不能保持任何類不變,並且值得注意的是不能保證不會有任何泄漏
  • 遵循神聖規則3:如果你寫了任何的析構函數,複製構造函數和賦值運算符,你需要寫另外兩個。這裏的拷貝構造函數和賦值操作符應該是protected以防止對象切片(儘可能多),並且他們應該關心內存。

現在的問題是:爲什麼你在這裏使用指針?

class Leaf 
{ 
public: 
    explicit Leaf(value_type data): mData(data) {} 

private: 
    value_type mData; 
}; 

看起來非常好,並且減輕了處理動態分配內存的繁瑣工作。

順便說一句,您的QuadTree類遭受同樣的問題:它缺少一個複製構造函數和賦值運算符。

+0

感謝您的提示。我通常不會得到很好的代碼評論,所以每一個小小的幫助。 在未編輯的Leaf類中,我有私人拷貝構造函數和賦值操作符,但最近我纔開始嘗試編寫這三個函數。 我想我有一些使用指針的理由,但我完全忘記了它。你的解決方案看起來更加健全。我會去修改代碼來刪除指針。 – m0tive 2010-07-06 15:06:06

+0

如果您計劃存儲多態類,則可以使用指針。然而,讓用戶決定他是否願意更容易。 – 2010-07-06 17:20:39