Factories are classes that make other classes. They are useful together with interfaces – abstract classes which specify functionality that is implemented somewhere else.
As opposed to including a header file for each implementation (which can take quite a while to compile), factories can be used to separate implementations into different object files, and add/remove functionality simply by adding/removing objects at link time.
Here is what I want:
An abstract (interface) class with a set of virtual functions
A simple way to register and create derived classes which implement this interface.
Code separation: I want to be able to put the implementation classes into a separate object file, and not require including any of their headers to use them (the interface header should be enough).
Make a factory interface (static functions or separate class):
…and a class to create this factory statically:
When implementing, include interface.h in a separate cpp file. Subclass and call REGISTER_INTERFACE.
We could also use the class name directly in the macro using stringification.
So, what have we achieved?
We can use the interface class without including headers for any of its implementations.
All implementations can live inside their own object file.
All implementations can be compiled separately.
UPDATE: Added this: (02/05/2013).
There is one small issue remaining:
The above code runs into trouble when the implementations go into a static library (rather than just linking object files). Then, a smart linker will optimise away the static registration objects. One way to address this is shown here:
In there, two macros are defined to create references which force the linker to include stuff:
This way, linking can be made to work by means of making an initialisation function (called at program startup) which calls all the FORCE_LINK_THAT’s, and inserting FORCE_LINK_THIS into REGISTER_INTERFACE.
This is not ideal, but still much faster than including full headers for each class which implements the interface (one more function and one more object).