2013-06-04 52 views
0

想象一下,有一个名为Node类,可容纳多的父母和多子女:两个成员彼此依赖?

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

的问题是,每次添加一个父节点,该节点的m_parents必须更新和家长的必须更新;这创建了一个无限循环。

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); 
} 

正如您所看到的那样,这并不好。 我设法通过添加四个方法来解决这个问题,而不是两个,但它感觉有点愚蠢。 附加的两种方法都被声明为privateprotected,所以他们不能被其他人调用。 这里的原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 
} 

这显然是addChild()rawAddParent()相同。

但是,这并不是一个合适的解决方案,当然也不清楚“外人”为什么有addChildrawAddChild方法。 我的逻辑有问题吗?如果是的话,我该如何解决这个问题?或者我的解决方案已经很好?

回答

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); 
} 
+0

请注意,你甚至可以摆脱近废人一个,留下你的代码的一种方法,而不是四个。呜! – slaphappy

+2

我正要提出你的解决方案,但我注意到“addParent”和“addChild”是虚拟的。如果派生类在添加子项时有某些特殊行为会怎么样?我会建议对您的答案进行一个修改,即:使“addParent”和“addChild”非虚拟,并且如果需要,添加派生类可以选择实现的“onParentAdded”和“onChildAdded”虚拟方法。 –

+1

我假设'Node'不是用于多态上下文中,并且'virtual'说明符因为任何特定的原因而不在这里。 – slaphappy

0

如果向量已经constains元素我会测试(可能使用集而不是矢量)

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

void Node::addChild(Node *child) 
{ 
    if (m_children.lacks(child)) { 
     m_children.push_back(child); 
    } 
    if (child->m_parents.find(this)==set::end) 
     child->addParent(this); 
} 
0

你应该抽象一点。

bool Node::addParent(Node *parent) 
{ 
    if (m_parents.lacks(parent)) { // supposing such method exists 
     m_parents.push_back(parent); 
     parent->updateRelationShip(parent,this); 
     return true; 
    } 
    return false; 
} 

bool Node::addChild(Node *child) 
{ 
    if (m_children.lacks(child)) { 
     m_children.push_back(child); 
     child->updateRelationShip(this,child); 
     return true; 
    } 
    return false; 
} 
void Node::updateRelationship(Node*parent, Node* child){ 
    parent->addChild(child); 
    child->addParent(parent); 
} 
+0

注意我半睡不着,所以不能完全确定是否有循环引用,但你明白了...... – dchhetri

相关问题