A Generic Factory in C++
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).
The full code is here: https://gist.github.com/pkrusche/5501253.
How to do it #
Make an interface:
Make a factory and a generic factory:
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.
{: .ui-state-highlight } 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:
http://stackoverflow.com/questions/599035/force-visual-studio-to-link-all-symbols-in-a-lib-file
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).