2

所以假设我在 C++ 中有一个像这样的树类

class Node{
    void addChild(Node*);
    /*obvious stuff*/
    protected:
        Node* parent;
        vector<Node*> children
}

class specialNode : public Node{
    void addChild(specialNode*);
    /*obvious stuff*/
    /*special stuff*/
}

现在,每当我访问 specialTree 中的子项时,我显然得到的是 Node*,而不是 specialNode*。

但是这个 specialNode* 有 Node 没有的成员变量和函数。

我可以强制 specialNode 只将 specialNode 作为子节点,否则会中断编译时间,但在访问子节点/父节点时我仍然会得到 Node*,并且每当我想使用特殊函数时,我都必须强制转换它,即使在 specialNode 函数中也是如此。

有什么聪明的,或者更好的方法来解决这个问题吗?除了每次都按字面意思投射?

4

4 回答 4

4

如果您只需要SpecialNode树中的对象(并且只想将所有通用树功能封装在 中Node),您可以创建Node一个所谓的“混合”类,例如

template <class N>
class Node : public N {
public:
  void addChild(Node<N>*);
protected:
  Node<N>* parent;
  vector<Node<N>*> children;
};

class SpecialNodeBase {
  // Here comes all "special" data/methods for your "special" tree
};

typedef Node<SpecialNodeBase> SpecialNode;

之后,您可以构建SpecialNode对象树并使用来自的所有方法SpecialNodeBase以及来自的其他树管理函数Node

于 2010-08-17T23:02:05.297 回答
0

因为子类中的 addChild 函数不是多态的,所以将其设为虚拟,但是不允许跨基/子成员重载函数,所以我们必须更改子类中的 addChild 参数:

class Node{
    virtual void addChild(Node*);
    ...
}

class specialNode : public Node{
    virtual void addChild(Node*);
    ...
}

现在,它应该可以工作了。


childeren如果你想从子类(类)访问变量specialNode,你应该强制转换它。例如:

specialNode* var = static_cast<specialNode*>(children[i]);

由于我们将 addChild 声明为虚函数,因此如果我们不确定它是否始终是类的实例,我们应该使用dynamic_cast而不是,因此最好使用:static_castchildren[i]specialNodedynamic_cast

specialNode* var = dynamic_cast<specialNode*>(children[i]);
if(var != NULL)
{
    //...
}
于 2010-08-17T22:59:23.647 回答
0

如果我理解正确,“混合”类解决方案将不允许您addChildSpecialNodeBaseClass.

您实际上可以执行以下操作:

template <class recursiveT>
class Base {
public:

     Base(dataType data) { populate children with data; }

     void addChild() { something base class appropriate; }

protected:
     std::vector<recursiveT> children;
};




class Derived: public Base<Derived> {
public:
     /* note: the constructor here will actually call the 
        constuctor of the base class */
     Derived(dataType data) : Base<Derived>(data) {} 
     /* other special functions go here.  */
};

这可能看起来有点疯狂,但它在几个 GCC 版本上为我编译得很干净,所以我倾向于相信它并不是完全错误的。您现在应该能够从 Derived 内部调用 Base 的函数。

于 2011-02-12T00:52:02.613 回答
-1

您肯定必须在某个时候将其Node *转换为 a specialNode *,但您可以通过仅在一个地方执行此操作来使其干净且易于管理。您可以添加一个成员函数,例如getParent并在 中覆盖它specialNode,如下所示:

class Node {
  ...
  virtual Node *getParent() {
    return parent;
  }
};

class specialNode : public Node {
  ...
  specialNode *getParent() {
    return dynamic_cast<specialNode *>(parent);
  }
};

当然,这是假设specialNodes 总是有其他specialNodes 作为父/子。如果你混合Nodes 和specialNodes,这显然是行不通的。

于 2010-08-17T23:01:33.470 回答