想象一下,有一个名为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
,并且必须更新父节点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);
}
如你所见,这并不好。
我已经设法通过添加四种方法来解决这个问题而不是两种方法,但感觉有点愚蠢。
另外两种方法都声明为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
}
对于addChild()
和rawAddParent()
,这显然是相同的。
然而,这并不是一个合适的解决方案,而且“外人”肯定不清楚为什么有addChild
和rawAddChild
方法。
我的逻辑是否存在问题,如果是,我该如何解决这个问题呢?或者我的解决方案已经很好了吗?
答案 0 :(得分: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);
}
答案 1 :(得分:0)
我会测试矢量是否已包含元素(可能使用set而不是vector)
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);
}
答案 2 :(得分: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);
}