我有一个树类,其中包含对子项数据进行操作的数据成员和成员函数:
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
中,父母和子女都应该(ExtTree*)
而不是(Tree*)
。如何重新组织此代码,以便ExtTree只添加自己的新数据,并使用旧方法返回Tree?
4年前提出了一个相关问题here,但我无法根据答案解决问题;特别是,ExtTree如何调用基础构造函数,或者如何访问Tree::method()
。
答案 0 :(得分:3)
通过将整个事物转换为模板,您将获得最佳,最安全的结果。
可以提出一个非基于模板的解决方案,但我不认为它会是最佳的。我建议使用基于模板的解决方案,但是,无论出于何种原因,模板都不会削减它,您可以通过以下方法获得可接受的结果:
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%类型安全的解决方案。
但是,我认为这将是很多工作。这就是模板的用途。使用它们。