我有tree_node
班和tree
班。
template<typename T>
class tree_node
{
public:
tree_node(const std::string& key_, const T& value_)
: key(key_), value(value_)
{
}
private:
T value;
std::string key;
};
template<typename T>
class tree
{
public:
tree() : root(new tree_node<T>("", ???)) { }
private:
tree_node<T>* root;
};
tree_node
在创建时需要T
的实例。我怎样才能在???
地方传递它?我可以说T()
,但只有当T
具有无参数构造函数时它才会起作用。我没有tree_node
的无参数构造函数,因为如果T
没有无参数构造函数,它将无法编译。
我正在寻找一种设计tree_node
的方法,它可以正确地保存所有类型,包括指针类型。
修改
尝试各种方法后,我发现boost::optional
在这种情况下很有帮助。我可以将T value
变成boost::optional<T> value
。这将解决空构造函数问题。所以我可以使用tree_node
的另一个构造函数重载,只需要key
。这可以由根节点使用。这是正确的方法吗?
谢谢..
答案 0 :(得分:4)
初始根值应该为零。如果你推新节点,你显然知道价值。
template<typename T>
class tree
{
public:
tree() : root(0) { }
void push (const std::string& key, const T & t) {
if (root == 0) {
root = new tree_node<T>(key, t);
} else {
// Make complex tree
}
}
private:
tree_node<T>* root;
};
添加强>
如果使用后缀树,则应制作两种类型的顶点:
enum NodeType { EMPTY_NODE, VALUE_NODE };
class base_tree_node
{
public:
base_tree_node() :parent(0), left(0), right(0) {}
virtual NodeType gettype() = 0;
protected:
base_tree_node* parent;
base_tree_node* left;
base_tree_node* right;
};
class empty_tree_node : base_tree_node
{
virtual NodeType gettype() { return EMPTY_NODE; }
}
template<typename T>
class tree_node : base_tree_node
{
public:
tree_node(const std::string& key_, const T& value_)
: key(key_), value(value_)
{
}
virtual NodeType gettype() { return VALUE_NODE; }
private:
T value;
std::string key;
};
答案 1 :(得分:3)
tree( const T & t ) : root(new tree_node<T>("", t )) { }
答案 2 :(得分:0)
我曾经做过一个链表(只是为了好玩),需要一个不需要保存任何数据的标记节点,我有以下结构:
struct BaseNode
{
BaseNode* next;
BaseNode(BaseNode* next): next(next) {}
};
template <class T>
struct Node: public BaseNode
{
T data;
Node(const T& data, BaseNode* next): BaseNode(next), data(data) {}
};
template <class T>
struct List
{
BaseNode* head;
List(): head(new BaseNode(0)) {}
void add(const T& value)
{
Node<T>* new_node = new Node<T>(value, head->next);
head->next = new_node;
}
T& get_first()
{
assert(head->next);
return static_cast<Node<T>*>(head->next)->data;
}
//...
};
类本身必须确保它具有正确的强制转换,并且不会尝试将head或root本身强制转换为Node<T>
。
答案 3 :(得分:0)
树节点应该具有(或者是)子节点的集合。树应该具有(或者是)根节点的集合。这两个集合应该是相同的类型。非常简单:
template <class T>
class NodeCollection
{
std::vector<Node<T> *> nodes;
public:
// any operations on collection of nodes
// copy ctor and destructor a must!
};
template <class T>
class Node : public NodeCollection<T>
{
T value;
public:
// ctor
// access to value
};
template <class T>
class Tree : public NodeCollection<T>
{
public:
// ctor
};
这样Tree
和Node
的共享定义实际上在NodeCollection
中,因此Tree
不需要携带虚拟值。