A solution to a Fragile-Base Class Problem It is possible to fortify at least a significant chunk of a class derivation tree, even against additions of virtual functions to a base class. This technique requires some discipline in building a hierarchy, but in return guarantees that only the top-most class needs to be recompiled to take into account modifications made to a base class. The rest of the hierarchy (which may have been compiled to a set of separate libraries) may be used as it is. The following scenario illustrates the technique. Act 1: Initial Setup Vendor A distributes a C++ stream library, which implements, among other things, classes Filebuf and Strstream. The library interface is iostream_v1.h, with a compiled code in iostream_v1.o Using the C++ stream library (distributed by Vendor A as iostream_v1), Vendor B builds a transaction service, class transaction_fofstream. This class adds commit/backoff functionality to the regular C++ file stream. This transaction_fofstream redirects all incoming information into a memory buffer; it is when the user commits() that all the accumulated data are written into a destination file. Vendor B distributes the package as a "library" (object file) "transstream_v1.o" with an interface "transstream_v1.h" A user acquires both libraries for use in his own code, module root_v1.cc . He derives a class MyTransaction from transaction_fofstream, instantiates MyTransaction, and uses it as a commit-able output stream. The resulting class hierarchy then looks as follows: MyTransaction (a class created and ultimately used by a user) transaction_fofstream (distributed by Vendor B in transstream_v1 package) - implements commit() and backoff() Strstream (distributed by Vendor A in iostream_v1 package) - provides str(), pcount(), freeze() methods along with the standard iostream applicators, a suite of operator's << To run this Act 1, enter make v1 which builds Vendor's A "library", Vendor B's "library", and user's executable code Act 2: Upgrade Now assume that the vendor A has decided to enhance his library: make it thread-safe. To this end, he added a mutex to the Strstream class to enable a thread to obtain an exclusive access to the stream's buffer. To make the design more flexible, the vendor also added a virtual function to operate this mutex lock, so that a derived class could find out that control has entered or about to enter a critical section. Rather than modifying the existing Strstream class, the vendor ought to create a new, extended version of it (see "strstream_v2.h"). This is the discipline one has to stick to. The vendor distributes that patch as a compiled code "strstream_v2.o", with an interface described in "strstream_v2.h". Since the patch does not have any name clashes or other conflicts with the old code, the vendor could just as well distribute the patch with a new version of his iostream library. Since none of the old functionality changed, the original user's code, root_v1.cc, will continue to compile and run as it is: no corrections are necessary. Suppose however that the user wants to take advantage of the new multi-threading capabilities of the iostream_v2 library. The only thing he needs to do is to modify his top-level class MyTransaction (see root_v2.cc). The class hierarchy thus becomes MyTransaction (a class created and ultimately used by a user) transaction_fofstream (from the original transstream_v1 package) - implements commit() and backoff() strstream_v2 (the update by Vendor A) - adds a mutex as a private data member - re-implements str(), and freeze() methods of Strstream to lock the stream's buffer when the stream is "frozen" - adds a virtual method "lock()" to operate on the mutex Strstream (from the original iostream_v1 package) - provides str(), pcount(), freeze() methods along with the standard iostream applicators, a suite of operator's << Note, strstream_v2 effectively supplants the old base class Strstream. When transaction_fofstream class commits a transaction, the stream becomes locked during this time. NOTE! Although functionality of transaction_fofstream is enhanced, the class itself did NOT require any modification or recompilation. The user keeps using the original Vendor's B package in its binary form. In fact, the user does not even have the source code for any of the libraries. The Upshot When a base class of a class hierarchy is extended with new data members, overridden virtual methods, or even with new virtual functions, it is nevertheless possible to avoid rebuilding of the entire hierarchy. One can bypass recompilation for a rather long limb of a class derivation tree. To see all this for yourself, enter make v2 which builds the Vendor A patch library, and runs the user code that takes advantage of it. Vendor's B library can be used as it is, no recompilation necessary.