我有一个树类,其中包括数据成员和对子代数据进行操作的成员函数:
class Tree {
// variables, member functions here
Tree *parent;
std::vector<Tree*> children;
public:
Tree(Tree* parent, int par0 /*, other constructor parameters*/) {
//....
this->parent = parent;
for (int n = 0; n < par0; n++)
children.push_back(new Tree(this, /*other arguments*/));
//...
}
void method() {
for (auto node: children)
node->method();
if (children.size() == 0) {
// Code for leaf nodes
} else {
// Code for internal nodes
}
}
};
Tree构造函数创建树结构,根据参数分配和初始化每个节点。
我想向该类添加新的数据和函数,从而产生新的类
ExtTree
,该类可以访问Tree
的所有数据和函数,并与之尽可能共享代码。但是,在ExtTree
中, parent 和 child 都应该是(ExtTree*)
而不是(Tree*)
。我如何重新组织这段代码,以便ExtTree仅添加自己的新数据,而在Tree上使用旧方法呢?4年前,有人问了一个相关问题here,但是我无法根据答案得出解决方案。特别是ExtTree如何调用基本构造函数,或如何访问
Tree::method()
。 最佳答案
通过将整个内容转换为模板,您将获得最佳,最安全的类型结果。
可以提出基于非模板的解决方案,但是我认为这不是最佳的。我建议使用基于模板的解决方案,但是,由于某种原因,如果模板无法进行裁剪,您可以通过以下方法获得可接受的结果:
A)定义一个虚拟方法:ExtTree *get_extree()
。 Tree::get_extree()
返回nullptr
或引发异常(取决于您,以最适合您的应用程序的情况为准)。 ExtTree::get_extree()
返回this
。
B)定义另一个称为create_node()
的虚拟方法。 Tree::create_node()
执行new Tree( /* forwarded parameters */)
,而ExtTree::create_node()
执行new ExtTree( /* forwarded parameters */)
。
C)将所有现有的new Tree
调用替换为对create_node()
的调用。
D)以及需要同时使用Tree
和ExtTree
的任何其他常见代码放置原因,都将使用get_extree()
来确定它的工作方式。
这将或多或少地带您到达您想去的地方。 A)从概念上讲,仅使用dynamic_cast
()几乎没有什么不同,并且使用dynamic_cast
代替get_extree
()没什么问题。但是有时候您会遇到对dynamic_cast
过敏的人,这是避免这种情况的一种方法。
我认为这里没有真正完美的,100%干净的,非基于模板的解决方案。通过创建大量虚拟方法并将几乎所有内容都实现为虚拟方法,这里可以获得100%类型安全的解决方案。
但是,我认为这将需要大量工作。这确实是模板的用途。使用它们。