不能在另一个类中使用类作为模板类型?

时间:2012-04-14 02:08:20

标签: c++

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

该堆栈适用于intdoublestringchar .... 但它说

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

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

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

帮助!

2 个答案:

答案 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的构造函数以datanext作为参数,因此您不需要在其模板类型上使用默认构造函数(您仍需要赋值运算符可用。)