我有一个Stack类,使用模板,其中一个方法是“push”,如下所示:
template <class T>
void Stack<T>::push(T _data){
Node<T>* temp = new Node<T>;
temp->data = _data;
temp->next = head;
head = temp;
}
该堆栈适用于int
,double
,string
,char
....
但它说
prog.cpp:32: note: synthesized method ‘Node<Tree>::Node()’ first required here
当我使用类“Tree”作为数据类型时。 我不明白,为什么它适用于“字符串”但不适用于“树”,它们都是类,而不是原始类型。
http://ideone.com/NMxeF (忽略另一个错误,我的IDE只在第32行发出一个错误并发出一些警告)
帮助!
答案 0 :(得分:4)
阅读实际代码后编辑(上面显示的“注释”对于真正的问题是相当误导的。)
查看代码,尝试使用new Node<T>;
,需要T的默认构造函数(在本例中为Tree
),因为您的Node模板包含T的实例:
struct Node {
T data; // <--- instance of T, not being initialized in your code.
Node *next;
};
Tree
没有默认构造函数,因此失败(并且注释显示了需要默认构造函数的位置)。
您有一些选择如何解决这个问题。最明显的是,Node
可以保存指针或对T
的引用,而不是包含实际的T实例。
另一种方法是让Node
的构造函数接受对(可能是const)T的引用,并将该T复制到Node中:
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可以保持快速和廉价的复制,同时避免编写仅适用于几种对象和情况的节点。这也明确表示您只存储一个指针,该指针提供对原始对象的共享访问。
答案 1 :(得分:4)
你有Tree
的默认构造函数吗?如果没有,那可能是您的问题:节点在其data
成员中保留Tree
类型,当您致电new Node<Tree>
时,该类型必须默认构建。
要修复,您可以修改Node
的构造函数以data
和next
作为参数,因此您不需要在其模板类型上使用默认构造函数(您仍需要赋值运算符可用。)