我有一个递归类,一种树,它有自己的实例作为成员变量。例如:
template<class T>
class Tree {
public:
/* Constructors, etc. */
protected:
T m_value;
Tree<T> *leftChild;
Tree<T> *rightChild;
};
如果我想添加一个使用有序遍历打印所有值的方法,我可以这样做:
template <class T>
void Tree<T>::printInOrder()
{
leftChild->printInOrder();
std::cout << m_value << std::endl;
rightChild->printInOrder();
}
但是,如果出于各种原因,我不能或不想改变Tree的实现呢?如果类不是递归的,即不包含它自己的实例,我可以从Tree派生并在派生类中实现一个新方法。但这种方法对Tree不起作用。
template <class T>
class DerivedClass : public Tree<T> {
public:
void printInOrder();
}
template <class T>
void DerivedClass<T>::
printInOrder()
{
this->leftChild->printInOrder();
std::cout << this->m_value << std::endl;
this->rightChild->printInOrder();
}
leftChild和rightChild是Tree的实例,因此没有printInOrder()方法。
任何人都可以建议一种方法,以模块化方式执行此操作,而无需更改Tree的实现。只要您不想在每次扩展/派生时更改它,就可以改变它的实现方式。我可以看到一种可能的方法,通过使模板类T有方法来做我想要的东西,但这看起来很难看。必须有更好的方法。
我很高兴有人指出我是如何忽略了一些显而易见的事情。它当然感觉像我一样。
编辑:关键不在于如何实现printInOrder()。那只是一个例子。关键是如何派生一个类,以便孩子们也是派生类。
答案 0 :(得分:1)
节点类型上的模板。
template<typename T, typename NodeType = void> class Tree {
NodeType node;
T m_data;
};
template<typename T> class Tree<void> {
struct Node {
Tree<T, void>* left;
Tree<T, void>* right;
};
Node node;
T m_data;
};
template<typename T> struct DerivedNode {
DerivedTree<T>* left;
DerivedTree<T>* right;
};
template<typename T> class DerivedTree : public Tree<T, DerivedNode<T>> {
// now left and right are of type DerivedTree<T>*.
};
这基于两个不变量 - Tree<T, NodeT>
为所有NodeT
提供相同的界面,而DerivedTree<T>
继承自Tree<T, ...>
。
编辑:该死的,为了防止Tree<T, NodeType>
的递归实例化而花费了很多精力。
答案 1 :(得分:0)
使printInOrder
成为virtual
函数,并在Tree
中使其可用。
这意味着,chilren可以是Tree
的任意后代,如果它们提供任何后代,则调用printInOrder
将始终调用覆盖实现。
主要缺点是所有方法都需要在Tree
中声明。
答案 2 :(得分:0)
您只需编写一个将实例打印的成员函数:
template <class T>
void DerivedClass::printInOrderHelper(const Tree<T>& tree)
{
printInOrderHelper(tree->leftChild);
std::cout << tree->m_value << std::endl;
printInOrderHelper(tree->rightChild);
}
在零参数过载中使用它:
template <class T>
void DerivedClass::printInOrder()
{
printInOrderHelper(*this);
}
答案 3 :(得分:0)
如果您想要非侵入式打印,只需为它指定一个普通的模板函数:
template <typename T>
void TreePrinter(const Tree<T>& tree)
{
TreePrinter(tree.leftChild);
std::cout << tree.m_value << std::endl;
TreePrinter(tree.rightChild);
}
你显然需要一个TreePrinter作为朋友:
template<class T>
class Tree {
public:
/* Constructors, etc. */
protected:
T m_value;
Tree<T> *leftChild;
Tree<T> *rightChild;
friend template <typename U>
TreePrinter(const Tree<U>&);
};
或者,如果您不将其作为朋友,请提供访问者以获取值以及树的左右节点。
答案 4 :(得分:0)
你能接受吗?
template <class T>void DerivedClass<T>::printInOrder()
{
((DerivedClass<T>*)leftChild)->printInOrder();
std::cout << this->m_value << std::endl;
((DerivedClass<T>*)rightChild)->printInOrder();
}