I am writing a static library for C/C++ (personal project). As my headers became rather large, I thought that splitting my headers would be a good idea.
Right now a header looks like this:
MainClass.hpp:
- namespace impl: implementation details enclosed in a namespace
impl
- forward declarations of classes declared below (when needed)
MainClass
declarationMainClass
free functions declarationsMainClass
specialization declarationMainClass
specialization free function declarationsAuxiliaryClass1
declarationAuxiliaryClass1
free functions declarations- …
AuxiliaryClassN
declarationAuxiliaryClassN
free functions declarationsMainClass
definitionMainClass
free functions definitionsMainClass
specialization definitionMainClass
specialization free function definitionAuxiliaryClass1
definitionAuxiliaryClass1
free functions definitions- …
AuxiliaryClassN
definitionAuxiliaryClassN
free functions definitions
- namespace impl: implementation details enclosed in a namespace
Where:
AuxiliaryClassK
is a class logically or structurally related toMainClass
(e.g. an iterator forMainClass
, a nested class withinMainClass
, a derived class ofMainClass
etc.)ClassX
free functions as recommended in How Non-Member Functions Improve Encapsulation and Monoliths "Unstrung"- definitions are in header because they are templates.
This is becoming very crowded and difficult for me to navigate so I thought that splitting across multiple headers would help. However I do not know how to do it right.
Here is how I think the structure could look like:
MainClass.hpp:
- forward declarations (when needed)
- small classes/structs definitions & declarations
#include
the other headers
_Class.hpp:
_Class
declaration_Class
free functions declarations
- _Class.inl:
_Class
definition_Class
free functions definitions
With a _Class
for each: MainClass
, MainClass
specialization, AuxiliaryClassK
.
My questions are:
- Is it reasonable to want to split a header (all are functionalities of
MainClass
) (I have headers over 1000 lines long and I foresee even longer ones) or should I leave it as it is? - Is the above split scheme ok? Should I further split a class and the free functions related to that class? Are there other solutions to make the code more maintainable?
- How to hide the other headers (not in a sense of obfuscating / making the code unavailable, but avoid exposing the headers the users see (e.g. in a GUI with autocomplete)? They should include and be aware only of
MainClass.hpp
. Seeing other headers without being clear that they are behind–the–scenes headers will produce unnecessary confusion. One idea is to add a prefix like an_
(underscore) or to put them in aimpl
folder. (Again, this is not about hiding classes (I do that with a namespace), but to hide the split behind a header they should use).