1

我有一个类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

当我使用类“树”作为数据类型时。我不明白,为什么它适用于“字符串”而不适用于“树”,它们都是类,而不是原始类型。

http://ideone.com/NMxeF (忽略另一个错误,我的 IDE 在第 32 行只给出一个错误和一些警告)

帮助!

4

2 回答 2

4

阅读实际代码后进行编辑(上面显示的“注释”对真正的问题具有相当大的误导性)。

查看您尝试使用的代码,new Node<T>;它需要 T 的默认构造函数(在本例中为Tree),因为您的 Node 模板包含 T 的实例:

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

Tree没有默认构造函数,因此失败(并且注释向您显示需要默认构造函数的位置)。

关于如何解决这个问题,您有几个选择。最明显的是 aNode持有一个指针或对 a 的引用,T而不是包含 T 的实际实例。

另一种方法是让Node的构造函数引用一个(可能是 const)T,并将该 T 复制到节点中:

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

这两种方法之间的选择是相当基本的。如果您让 Node 存储一个指向 T 的指针/引用,那么只要 Node 存在,调用代码将负责确保传递的对象保持有效。节点和调用代码将共享对 T 的单个实例的访问。

相反,如果你将传递的对象复制到 Node 中,那么这个副本将在销毁时Node被销毁。您传递给节点的原始 T (在您的情况下为树)仍将由调用代码负责,并且Node将对其副本负责。

通常情况下,您倾向于支持后者——它提供更清晰的语义,并保持数据的所有权清晰。但是,在树的情况下,如果可以避免的话,您可能不想将整个树复制到节点中。一种折衷的立场是使用类似 a 的东西Node<shared_ptr<Tree> >。shared_ptr 可以保持快速且廉价的复制,同时避免编写仅适用于少数几种对象和情况的节点。这也非常明确地表明您只存储了一个指针,该指针提供对原始对象的共享访问。

于 2012-04-14T02:13:55.997 回答
4

你有默认构造函数Tree吗?如果不是,那可能是您的问题: Node 在其data成员中包含一个Tree类型,当您调用new Node<Tree>.

要解决此问题,您可以修改Node的构造函数以将dataandnext作为参数,因此您不需要在其模板类型上使用默认构造函数(您仍然需要赋值运算符可用)。

于 2012-04-14T02:14:40.923 回答