I need to keep a list(vector) of children for every class, and I’ve got a tricky problem:
class A
{
protected:
int a;
static vector<A*> children;
public:
A(int a): a(a) {;};
virtual void AddToChildren(A* obj);
virtual void ShowChildren();
virtual void Show();
};
class B: public A
{
protected:
int b;
static vector<A*> children;
public:
B(int a, int b): b(b), A(a) { A::AddToChildren(this);};
virtual void Show();
};
class C: public B
{
protected:
int c;
public:
C(int a, int b, int c): c(c), B(a,b) { B::AddToChildren(this);};
virtual void Show();
};
vector<A*> A::children=vector<A*>();
vector<A*> B::children=vector<A*>();
void A::AddToChildren(A *obj)
{
children.push_back(obj);
}
void A::ShowChildren()
{
for(vector<A*>::iterator i=children.begin(); i!=children.end();i++)
(*i)->Show();
}
Adding A(0), B(1,1) and C(2,2,2) and calling a.ShowChildren gives: 1,1 ; 2,2,2 ; 2,2,2
Every time I make an instance of class C the A::children is updated instead of B::children and A::children. Sooo… the class C is added twice to the children of A class, but not added to class B. It helps when I copy the AddChildren class (literally copy) to class B, so that every class has its own AddChildren/ShowChildren. Also I’ve managed to accomplish this task using pointers, but I’m wondering is there a better way. I think that the problem is somewhere in the “using the right vector”, but I don’t know how to force the compiler to use the right one.
I would be grateful for any suggestions on whatever I’m doing wrong here.
First of all, thank you all for your comments and help. Using your advice (about my design and virtual GetList()) I managed to simplify my program:
class A
{
protected:
int a;
virtual vector<A*>* GetList();
public:
A(int a): a(a) {;};
A(int a, A* inherited):a(a) { AddToChildren(inherited);};
static vector<A*> children;
virtual void AddToChildren(A* obj);
virtual void ShowChildren();
virtual void Show();
};
class B: public A
{
protected:
int b;
virtual vector<A*>* GetList();
public:
static vector<A*> children;
B(int a, int b): b(b), A(a,this){;};
B(int a, int b, A* inherited) : b(b), A(a,this){AddToChildren(inherited);};
virtual void Show();
};
class C: public B
{
protected:
int c;
public:
C(int a, int b, int c): c(c), B(a,b,this) { };
virtual void Show();
virtual vector<A*>* GetList();
};
vector<A*> A::children=vector<A*>();
vector<A*> B::children=vector<A*>();
void A::AddToChildren(A *obj)
{
GetList()->push_back(obj);
}
void A::ShowChildren()
{
for(vector<A*>::iterator i=GetList()->begin(); i!=GetList()->end();i++)
(*i)->Show();
}
vector<A*> * A::GetList()
{
return & children;
}
vector<A*> * B::GetList()
{
return & children;
}
vector<A*> * C::GetList()
{
return & children;
}
Now its using constructors without calling the upper class, it just calls the proper constructor of the upper class. Its not the best, but i think it’s better.
Once more, thank you all for help.
Your design intent is not sufficiently clear, which is why the authors of some other answers got confused in their replies.
In your code you seem to make calls to
AddToChildrenfrom some constructors but not from the others. For example, you have achildrenlist inAbut you never call theAddToChildrenfromA::Aconstructor. Also, classChas no its ownchildrenlist. Why? Is it supposed to share thechildrenlist withB?I can guess that the fact that you are not calling
AddToChildrenfrom all constructors means that some constructors are intended to build complete “objects” of given type (these constructors do callAddToChildren), while some other constructors are intended to be used as “intermediate” constructors by descendant classes (these constructors don’t callAddToChildren).Such design might be considered quite questionable and error prone. Note, for example, that
C::CcallsAddToChildren, which supposedly is addingthistoB::children(was it the intent?), and also invokesB::Bconstructor, which will also addthistoB::children. So, the samethisvalue is added to the list twice. This does not seem to make any sense.You need to figure out what is it you are trying to do and then fix your design. Once you are done with it, you can “virtualize” the list using the technique proposed by Neil (introducing a virtual
GetListmethod). Neil later wrote incorrectly that it will not work. In fact, it will work perfectly fine (again, assuming that I understand your intended design correctly).(Taking into account the OP’s clarifying comments)
So, you want
Bobjects to be added toA::childrenlist andCobjects to be added to bothA::childrenandB::childrenlists. This can be achieved byNote that despite what was said by other posters, virtual calls do work here and they work exactly as we need them to work to achieve the requested functionality. Note though, that in this case there’s no point to make method
AddToChildrenvirtual, the virtuality ofGetListalone is sufficient.Also, the whole thing makes little if
AddToChildrenjust does apush_back. There’s no much sense the build such infrastructure for such a “thin”AddToChildrenalone. Just do what you want to do explicitly in each constructor.