Container of a hierarchy of objects

How do we design a container of objects all of which belong to some subclass which directly/indirectly inherits from a given parent class? Moreover, I would like to have functions that enable me to pick only objects of a certain class type from the container.
For example if the parent class is A and I have a hierarchy of classes that derive from it, we must have a container that can contain any class that exists in this hierarchy. Also, get_B() must be able to let me examine only those objects in this container that inherit (directly/indirectly) from class B (class B exists in the hierarchy rooted at A).

Preferably, we would like to avoid downcasting. Or even explicit typechecking of any sort.
Last edited on
container of pointers std::vector<A*> or some smart pointers.

get_B() must be able to let me examine only those objects in this container that inherit
1
2
3
4
5
6
7
8
9
10
std::vector<B*> get_B()
{
    std::vector<B*> result;
    for(auto p: container) {
        B* tmp = dynamic_cast<B>(p);
        if (tmp)
            result.push_back(tmp);
    }
    return result;
}

we would like to avoid downcasting.
Store some type of identifier in your objects.
1
2
3
    for(auto p: container) {
        if (p->type == "B")
        result.push_back(p);


Also you can have virtual is_B() function which B overloads to return true, but it is plain ugly.
Last edited on
p is of type A* and won't pushing that into a std::vector<B*> be equivalent to a downcast?
I did come up with a solution similar to yours. In that context, is there a neater way of storing the type information in the object? By using the power of namespace, possibly? I'm not very sure, but well, is there a better way of doing it, rather than hard-coding it like you've suggested?
Well, the design approach with inheritance and using pointer/reference to the base class is that you should not know exactly what type you are operating on. Every difference should be managed by class itself. If you need to downcast, you did something wron from the design approach. Why would you need to take B objects? Wouldn't it be better to just store them separately from the beginning?

p is of type A* and won't pushing that into a std::vector<B*> be equivalent to a downcast?
Where I am pushing it tht way? Notice that I did not write anything about result and function return type in second snippet.
Where I am pushing it tht way?


In your solution:

1
2
3
 for(auto p: container) {
        if (p->type == "B")
        result.push_back(p);


isn't result of type std::vector<B*> ? Also, isn't p a pointer of type A* used to iterate through an original list of A* objects?

Wouldn't it be better to just store them separately from the beginning?


Exactly. That is just another solution. What I'm looking for in the end, is some container class that can neatly handle all this by storing them as required.
But if I had stored them separately, remember that I have a hierarchy of classes. That is, if I need to pick objects of B I should also be able to pick objects that belong to classes that derive from it if the request is get_B().
enigman wrote:
isn't result of type std::vector<B*>
Nope I did not write that anywhere.
MiiNiPaa wrote:
Notice that I did not write anything about result and function return type in second snippet.


I have a hierarchy of classes. That is, if I need to pick objects of B I should also be able to pick objects that belong to classes that derive from it if the request is get_B().
Store B objects and derived in B*, Everything else in A* containers.

But main question is why B objects are getting special threatment? can't you do this transparently through base pointer? Shouldn\t you change your architecture?
It's not just the B objects. Any of the classes in the hierarchy must be identifiable.
If you need to be able to identify every single class in hierarchy, you are using inheritance wrong.
Topic archived. No new replies allowed.