我有一个树类,其中包括数据成员和对子代数据进行操作的成员函数:

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)以及需要同时使用TreeExtTree的任何其他常见代码放置原因,都将使用get_extree()来确定它的工作方式。

这将或多或少地带您到达您想去的地方。 A)从概念上讲,仅使用dynamic_cast()几乎没有什么不同,并且使用dynamic_cast代替get_extree()没什么问题。但是有时候您会遇到对dynamic_cast过敏的人,这是避免这种情况的一种方法。

我认为这里没有真正完美的,100%干净的,非基于模板的解决方案。通过创建大量虚拟方法并将几乎所有内容都实现为虚拟方法,这里可以获得100%类型安全的解决方案。

但是,我认为这将需要大量工作。这确实是模板的用途。使用它们。

09-11 05:51