c++处理自引用的派生类

发布于 2024-09-15 03:53:31 字数 564 浏览 10 评论 0原文

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

但是这个特殊的Node*具有Node所没有的成员变量和函数。

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

有什么聪明的或者更好的方法来解决这个问题吗? 除了每次都直接铸造之外?

So suppose I have a tree class like this in 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*/
}

Now whenever I access the children in specialTree, I obviously get Node*, not specialNode*.

But this specialNode* has member variables and functions that Node doesn't have.

I can force specialNode to only have take specialNode as children and otherwise break in compile time,
but I still get Node* when accessing children/parent, and I have to cast it whenever I want to use special functions, even in specialNode functions.

Is there any clever, or just any better way to go about this?
Other than literally casting every time?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

冷了相思 2024-09-22 03:53:31

如果您的树中只需要 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 的其他树管理函数

If you only need SpecialNode objects in your tree (and just want to encapsulate all generic tree functionality in Node) you can make Node a so called "mix-in" class like

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;

After that you can construct a tree of SpecialNode objects and use all methods from SpecialNodeBase as well as additional tree-managing functions from Node

只等公子 2024-09-22 03:53:31

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

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

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

现在,它应该可以工作。


如果您想从子类(specialNode 类)访问 childeren 变量,则应该对其进行强制转换。例如:

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

由于我们将 addChild 声明为虚函数,因此如果我们不确定 children[i] ,我们应该使用 dynamic_cast 而不是 static_cast code> 始终是 specialNode 类的实例,因此最好使用 dynamic_cast

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

Because addChild function in your child class is not polymorphism, make it virtual, but overloading functions across base/child members is not allowed, so we have to change the addChild parameter in the child class:

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

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

Now, it should work.


If you want to access to the childeren variable from the child class (specialNode class), you should cast it. For example:

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

Since we declared addChild as a virtual function, then we should use dynamic_cast instead of static_cast if we aren't sure that children[i] is always an instance of specialNode class, and thus it is better to use dynamic_cast:

specialNode* var = dynamic_cast<specialNode*>(children[i]);
if(var != NULL)
{
    //...
}
节枝 2024-09-22 03:53:31

如果我理解正确,“混合”类解决方案将不允许您从 SpecialNodeBaseClass 实现的函数中调用 addChild

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

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 的函数。

If I understand correctly, the "Mix-in" class solution won't allow you to call addChild from functions implemented by SpecialNodeBaseClass.

You can actually do the following:

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.  */
};

This may look a little crazy, but it compiles cleanly for me on several GCC versions so I'm inclined to believe it's not totally wrong-headed. You should now be able to call the functions of Base from inside Derived.

煞人兵器 2024-09-22 03:53:31

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

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

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

当然,这是假设 specialNode 始终具有其他 specialNode 作为父/子节点。如果你混合使用NodespecialNode,这显然是行不通的。

You will definitely have to cast the Node * to a specialNode * at some point, but you can make this clean and easy to manage by doing this in only one place. You could add a member function, say getParent and override it in specialNode, like this:

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

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

Of course, this is assuming that specialNodes always have other specialNodes as parent/children. If you mix Nodes and specialNodes, this obviously won't work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文