2012-04-14 66 views
1

我有一個Stack類,使用模板,它的方法是 「推」,這是寫在下面:不能在另一個類中使用類作爲模板類型?

template <class T> 
void Stack<T>::push(T _data){ 
    Node<T>* temp = new Node<T>; 
    temp->data = _data; 
    temp->next = head; 
    head = temp; 
} 

棧運行良好與intdoublestringchar .... 但它說

prog.cpp:32: note: synthesized method ‘Node<Tree>::Node()’ first required here 

當我使用類「樹」作爲數據類型。 我不明白,爲什麼它使用「字符串」而不是「樹」,它們都是類,而不是原始類型。

http://ideone.com/NMxeF (忽略其他錯誤,我的IDE只給在第32行有一個錯誤和一些警告)

幫助!

回答

4

在閱讀實際代碼後(上面顯示的「註釋」相當令人誤解真正的問題)編輯。

的代碼,您嘗試使用new Node<T>;,需要對T(在這種情況下是Tree)一個默認的構造看,因爲你的節點模板包含T的實例:

struct Node { 
    T data; // <--- instance of T, not being initialized in your code. 
    Node *next; 
}; 

Tree沒有按沒有默認構造函數,因此失敗(並且註釋顯示了默認構造函數將需要的位置)。

你有幾個關於如何解決這個問題的選擇。最明顯的將是一個Node保持任一指針或到T一個參考,而不是含有T.

的實際實例的另一種辦法是有Node的構造採取一個(可能是常數)的參考T,並將該T複製到節點中:

class Node { 
    T data; 
    Node *next; 
public: 
    Node(T const &dat) : data(dat), next(0) {} 
}; 

這兩種方法之間的選擇是相當重要的。如果您有Node存儲對T的指針/引用,那麼調用代碼將負責確保只要Node存在,傳遞的對象就保持有效。節點和調用代碼將共享對T的單個實例的訪問。

相比之下,如果將傳遞的對象複製到節點中,則在銷燬Node時,該副本將被銷燬。您傳遞給節點的原始T(樹,在您的情況下)仍然是調用代碼的責任,並且Node將負責其副本。

通常的的情況下,你會傾向於後者 - 它提供了更清晰的語義,並保持數據清除的所有權。但是,對於樹,如果可以避免,則可能不希望將整個樹複製到節點中。一個妥協的立場是使用類似Node<shared_ptr<Tree> >的東西。 shared_ptr可以保持快速且廉價的複製,同時避免編寫僅適用於幾種對象和情況的節點。這也相當明確地表明,你只存儲了一個指向共享訪問原始對象的指針。

+0

+1爲不同的選項及其影響的不錯和徹底的解釋 – Attila 2012-04-14 09:36:56

4

你有一個Tree的默認構造函數嗎?如果不是,那可能是你的問題:節點在其data成員中保存一個Tree類型,當你調用new Node<Tree>時,該類型必須是默認構造的。

要解決,你可以修改Node的構造方法來datanext作爲參數,所以你不需要在它的模板類型的默認構造函數(你還需要賦值運算符可用)。

+0

我猜我不熟悉gcc的筆記,但這並不會改變我的答案的有效性 – Attila 2012-04-14 02:26:19

+0

這不是一個「注」(如果你把它稱爲「警告」),但是一個錯誤(導致程序無法編譯),所以我肯定需要修復它。無論如何,樹類的默認構造函數正是我錯過的。謝謝! – 2012-04-14 02:31:57

+0

請參閱我編輯的答案 - 查看他在IDEONE上放置的內容,他發佈的內容僅爲註釋,*但它與實際錯誤有關,在代碼工作之前需要修正。在看實際的代碼之前,我只根據問題中的內容對評論道歉。 – 2012-04-14 02:48:00

相關問題