tags:

views:

117

answers:

3

I have 3 classes, 2 inheriting from the other like so:

class A {
  public:
    virtual void foo() {cout << "I am A!" << endl;}
};

class B : public A {
  public:
    void foo() {cout << "B pretending to be A." << endl}
    void onlyBFoo() {cout << "I am B!" << endl}
};

class C : public A {
  public:
    void foo() {cout << "C pretending to be A." << endl}
    void onlyCFoo() {cout << "I am C!" << endl}
};

What I want to do is something like this:

list<A*> list_of_A;
list<B*> list_of_B;
list<C*> list_of_C;

//put three of each class in their respective list

cout << "First loop:" << endl;
for (list<B>::iterator it = list_of_B.begin(); it != list_of_B.end(); ++it) {
  (*it)->onlyBFoo();
}

cout << "Second loop:" << endl;
for (list<C>::iterator it = list_of_C.begin(); it != list_of_C.end(); ++it) {
  (*it)->onlyCFoo();
}

//This part I am not sure about
cout << "Third loop:" << endl;
for (Iterate all 3 loops i.e. *it points to As, then Bs then Cs) {
  (*it)->foo();
}

To output:

First loop:
I am B!
I am B!
I am B!

Second loop:
I am C!
I am C!
I am C!

Third loop:
I am A!
I am A!
I am A!
B pretending to be A.
B pretending to be A.
B pretending to be A.
C pretending to be A.
C pretending to be A.
C pretending to be A.

i.e. sometimes I want to only iterate the B objects, but sometimes I want to iterate all the objects.

One solution would be to store them all in a list, however I want to be able to loop through them in order of type i.e. the As then the Bs then the Cs.

Another suggested solution was to use iterators or iterator_adapters, however I have never used them before and can't find a simple example to help me get started with them.

A: 

If You want to have one list, You can iterate over, to call foo(), for all objects in a polymorphic way (that is, so the right version of foo() gets called for every object), You have to create a list of pointers to all Your objects stored in other containers and call foo() using those pointers. The pointers should be of the type A*.

I'm assuming that the ownership of Your objects belongs to those other containers.

Maciej Hehl
A: 

The boost iterator adapters might give you what you need - you can create a polymorphic list (all the items), and then create iterator adapters that iterate over only the B items, or only the C items. You could use the standard iterators to list all of the items.

As other folks mentioned, you need the polymorphic list to contain pointers, so that your items don't get sliced. You then need to manage the lifetime of the items, i.e. make sure you delete them when you delete the container. There are smart pointer classes that can make that task easier.

jwismar
This sounds like what I want, however I have not used iterators before and it looks complicated. Are there any simple examples you can show me?
Graham Rogers
A: 

I agree with your idea that having a single list would be easier to maintain those objects. The key point is that you need a way to know the dynamic type of objects in the list unless you want to add all sub class (like B, C) functions into your super class (like A) as empty virtual functions.

It doesn't matter whether if you use boost::filter_iterator (one of specialized adaptors in boost) since you still need to implement a predicate function to decide if this object is what you are looking for.

You might want to take a look at this : http://stackoverflow.com/questions/351845/finding-the-type-of-an-object-in-c I would say it's either using RTTI or adding your own type info into your class.

young