I'm afraid I don't know C++, so I can't offer any suggestions there. I can recommend that you take advantage of the type system, since you have one, to enforce constraints in your data structures rather than enforcing them in code. By this I mean (for instance) that if one object can have a relationship with any of a subset of the rest, strive to make it impossible for that object to relate to one of the other objects. In Java one would perhaps do this by making those objects implement a special interface, and having the one object relate to things with that interface. I know C++ has an equivalent (pure virtual classes?), but I don't know what it is.

One caveat is that it is quite possible to take this advice a little too far, and wind up with an overly complicated object model. It's a fine line, and quite hard to see where it is. I know that early on, I used to have a lot of simple object models whose constraints were enforced in code which seemed easiest, but much later in the project it made the program overall much more complicated, because as I built more and more code to manipulate the model, I found I was repeatedly having to enforce constraints that I might not even remember properly (or worse, not enforcing them at all, and encountering runtime errors due to situations that shouldn't have arisen in the first place). Later, I tried for more complicated models, but occasionally got paralyzed in attempting to capture every single constraint in a hugely complicated model. There's no principle for seeing the line that I can see, just painful experience.

If you have a C++ guru or mentor, try to get them to recommend a good C++ codebase with a good data model that you can use as a reference. If you can get one, you might study it carefully and contemplate the way they designed the model, considering what the alternative representations were, and what consequences would have arisen from using one of these alternatives. If you can discuss them with a guru, so much the better. I'd say this is how I learned the bulk of what I know (or think I know) about the design of object models.

One of the most influential experiences in my career was integrating a third-party framework that was under development into my employer's system, also under development. This meant that I didn't do much coding of my own, instead I was regularly taking new versions of the third party system, and figuring out how to weld it into our constantly changing codebase without changing either too much. To do this I had to spend a lot of time studying both systems and talking with developers and designers on both sides. I learned a lot from that. Fortunately, the designers of both systems (of the parts relevant to me, anyway) were really talented, and strove to do things the right way, even if it meant throwing things away or slipping the schedule a little. To this day I will often solve design problems by thinking back and theorizing how the designers of those systems would have done it.

I should also mention that the final redesigns I mentioned in my previous comment were almost always the result of my taking my hard-won lessons of the first month or so of coding, and sitting down for a week with a pencil and paper and just drawing object relationship diagrams instead of coding. I'd draw the diagrams, then mentally go over the various tasks the program would have to perform, imagining how it would manipulate the object model I had drawn before me. This exposed many flaws very early in the process, preventing me from doing much unnecessary coding. You can use a semi-formal methodology here (like UML, but without all of the formalism - you just need to have a clear way of representing object hierarchies). Simple boxes and lines are fine too.