2012-04-14 63 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

相关问题