I've moved this from Stack Overflow and this was the suggested place to ask. This has been marked as a possible duplicate of a question about the merits of composition over inheritance. I'm not asking that question, I'm looking for strategies to manage development given the code we have.
The context of the question is a set of applications written in C++ with Qt. We work in a pseudo agile manner, i.e. we have 2 week sprints but don't have frequent releases.
They are all variations of a theme but each modifies the one before it.
This is not an ideal scenario but what I have to work with.
So application A uses Alib. application B uses Blib and Alib; most of the classes in Blib are descendents of those in Alib. Similarly application C uses Alib Blib and Clib, which subclasses from Blib primarily but also occasionally Alib.
We use CVS and it is a proper pain in the neck to branch our builds as the MSVC projects never merge correctly.
What currently happens is a developer working on Alib can cause unforeseen issues in both Blib and Clib unless we adopt some strategy for review or rules on development.
We are under a lot of time pressure and don't currently have the time to reorganise the code, so I am looking for things we can do within the current framework.
If we were using git it would be easier to branch the code for each dev but again we're not currently there just yet (it is in the pipeline).
I'm thinking along the lines of requiring all new developments which alter (as opposed to add) functionality in ALib to subclass that behaviour.
Other options I've read about include "fail often" i.e. being brash about committing/changing the stuff in Alib and make sure that Blib and Clib are review often enough to keep up with the changes.
Similar to this is frequent code reviewing (one developer (me) has good knowledge of all three libs so should be able to spot potential downstream effects early), which begs the question pre or post commit.
Edit: Thanks for the broad range of solutions, I wish I could mark a couple of these as answers, but have gone with John W'us answer. He's articulated my dilemma quite well in the third point - trying to reduce repeating ourselves (i.e. don't violate DRY) while having some isolation for each lib. Ultimately a code refactor is in order, but more (some!) unit tests should highlight broken code. One issue we've had is that the developer in Alib would see their changes affecting Blib and Clib and go and change those in ways the developers of Blib and Clib didn't exactly appreciate. So a rule about keeping code closed (extend but don't modify) is also very pertinent.