Reputation: 217
I'm working on a C++ hierarchical tree-based class design, with two object types, A and B.
Type A objects can have any number of children, of type either A or B, but they must be stored in a single sequential order. Type B objects may not have any children.
My question is regarding the best OO practices for handling collections of mixed types in C++.
One solution I can see would be to create a Base class, which from which both classes A and B are derived, and for A to hold a vector<Base*> children
. This seems like a good solution except for down the line there is more likely to be some dynamic casting to determine child type, which I've been told can be a symptom of poor code design.
Another option would be for class A to hold a separate list of A and B children, along with a value to represent that child's position in the combined children list. This seems like a more problematic solution as when items are inserted, removed or rearranged, the position values must be manually maintained.
A third option would be to roll the functionality of classes A and B into one class and have a flag to note how to interpret the object.
Are these my only options for this problem? Am I missing some more elegant solution, or approaching it from the wrong direction? I've seen that Boost has some options for heterogenous collections but using Boost isn't an option in this project unfortunately.
EDIT: I'll try to describe the real case with some more details
Type A objects define collections. They hold string paths or patterns, to define a set of objects (from a user created pool). Children collections define further subets.
Type B objects are overrides. They describe operations to be applied to the set of objects defined by parent A objects.
The order of the collections and collections determines the order in which the overrides are applied.
The point where I was finding I needed to downcast was at an evaluation stage, where I was iterating through the tree to collate and apply the overrides - I needed to know how to treat each item in the tree and whether to look for location or override data. From the comments I've received it seems I should able to accomplish what I need with real OO design, so I'll have another go before I can equivocally say otherwise.
Upvotes: 0
Views: 395
Reputation: 119877
None of your proposed solutions have anything to do with OO or polymorphism or any such buzzword. (Not that there's any inherent problem with that).
The OO solution would be to rely exclusively on virtual functions in Base
to perform work specific to each particular derived class. Nothing more and nothing less.
Upvotes: 2
Reputation: 74028
With C++17, you might utilize std::variant
struct B {
// ...
};
struct A {
std::vector<std::variant<A, B> > children;
// ...
};
Upvotes: 2