Reputation: 2456
Imagine having a class called Node
that can hold multiple parents and multiple children:
class Node {
public:
Node();
virtual void addParent(Node *parent);
virtual void addChild(Node *child);
private:
vector<Node*> m_parents;
vector<Node*> m_children;
};
The problem is that every time you add a parent to a node, the node's m_parents
must be updated and the parent's m_children
must be updated; this creates an infinite loop.
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);
}
As you can see, it's no good.
I've managed to solve this by having four methods for adding instead of two, but it feels somewhat stupid.
The additional two methods are both declared private
or protected
so they can't be called by others.
Here's the original addParent
and a new method called 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
}
This would obviously be the same for addChild()
and rawAddParent()
.
However, this doesn't feel like a proper solution, and it's certainly not clear for "outsiders" why there's addChild
and rawAddChild
methods.
Is there a problem with my logic and if so, how should I solve such problem? Or is my solution already good?
Upvotes: 0
Views: 108
Reputation: 7136
You should abstract a little.
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);
}
Upvotes: 0
Reputation: 1429
I would test if the vector already constains the element (probably using set instead of 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);
}
Upvotes: 0
Reputation: 6999
I would suggest doing the actual operation in only one of the two methods:
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);
}
Upvotes: 7