所以假设我在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*/
}

现在,每当我在特殊树木中访问孩子时,我显然会得到节点*,而不是SpecialNode*。

但是,此特殊Node*具有Node没有的成员变量和函数。

我可以强迫SpecialNode只能将Special Node作为孩子,而在编译时间中会中断,但是在访问孩子/父母时,我仍然会得到Node*,即使我想使用特殊功能,即使在Special Nonode功能中,我也必须施放它。

有什么聪明的,还是有什么更好的方法?除了每次铸造吗?

有帮助吗?

解决方案

如果您只需要 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

其他提示

因为您的子类中的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_cast 如果我们不确定 children[i] 总是一个实例 specialNode 班级,因此最好使用 dynamic_cast:

specialNode* var = dynamic_cast<specialNode*>(children[i]);
if(var != NULL)
{
    //...
}

如果我正确理解,“混合”类解决方案将不允许您致电 addChild 从实施的功能 SpecialNodeBaseClass.

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

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版本上对我来说很干净,所以我倾向于认为这不是完全错误的。现在,您应该能够从内部派生中调用碱的功能。

您一定必须施放 Node *specialNode * 在某个时候,您只能在一个地方进行此操作,可以使这种干净易于管理。您可以添加成员功能,说 getParent 并覆盖它 specialNode, , 像这样:

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

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

当然,这是假设 specialNodeS总是有其他 specialNode作为父母/孩子。如果您混合 NodespecialNodeS,这显然无法正常工作。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top