两个成员互相依赖?

Ska*_*One 0 c++ design-patterns

想象一下,有一个叫做Node可以容纳多个父母和多个孩子的班级:

class Node {
    public:
        Node();
        virtual void addParent(Node *parent);
        virtual void addChild(Node *child);
    private:
        vector<Node*> m_parents;
        vector<Node*> m_children;
};
Run Code Online (Sandbox Code Playgroud)

问题是每次向节点添加父节点时,m_parents必须更新节点并且必须更新父节点m_children; 这会产生无限循环.

void Node::addParent(Node *parent)
{
    if (m_parents.lacks(parent)) { // supposing such method exists
        m_parents.push_back(parent);
    }
    parent->addChild(this);
}

void Node::addChild(Node *child)
{
    if (m_children.lacks(child)) {
        m_children.push_back(child);
    }
    child->addParent(this);
}
Run Code Online (Sandbox Code Playgroud)

如你所见,这并不好.我设法通过添加四种方法来解决这个问题而不是两种方法,但感觉有点愚蠢.另外两种方法都是声明的private,protected因此不能被其他方法调用.这是原始addParent和新方法,称为rawAddChild:

void Node::addParent(Node *parent)
{
    if (m_parents.lacks(parent)) {
        m_parents.push_back(parent);
    }
    parent->rawAddChild(this);
}

void Node::rawAddChild(Node *child)
{
    if (m_children.lacks(child)) {
        m_children.push_back(child);
    }
    // Doesn't call for parent's method
}
Run Code Online (Sandbox Code Playgroud)

对于addChild()和,这显然是相同的rawAddParent().

然而,这并不觉得自己是一个妥善的解决办法,它肯定不明确的"外人"为什么有addChildrawAddChild方法.我的逻辑是否存在问题,如果是,我该如何解决这个问题呢?或者我的解决方案已经很好了?

sla*_*ppy 7

我建议只在两种方法中的一种方法中进行实际操作:

void Node::addParent(Node *parent)
{
    if (m_parents.lacks(parent)) {
        m_parents.push_back(parent);
    }
    if (parent->m_children.lacks(this)) {
        parent->m_children.push_back(this);
    }
}

void Node::addChild(Node *child)
{
    child->addParent(this);
}
Run Code Online (Sandbox Code Playgroud)

  • 我打算建议你的解决方案,但我注意到"addParent"和"addChild"是虚拟的.如果派生类在添加子项时有某些特殊行为会怎样?我建议对你的答案进行一次修改,即:使"addParent"和"addChild"非虚拟,如果需要,添加"onParentAdded"和"onChildAdded"虚拟方法,派生类可以选择实现这些方法. (2认同)