Updated about 12 years ago by Knödlseder Jürgen
Coding techniques¶
This pages summarizes some coding techniques that are used in GammaLib.
Interface classes¶
Interface classes are widely used throughout GammaLib. An interface class is an abstract virtual base class, i.e. all class that only has pure virtual methods. This forces the derives class to implement all the pure virtual methods.
Registries¶
Registries are widely used in GammaLib to collect the various derived classes that may exist for a base class. This allows automatic recognition of GammaLib of all derived classes that exist, and this even without recompilation of the code. One area where registries are widely used are model components. For example, by defining GModelSpectralRegistry
class, all spectral models that are available through a registry, allowing for example automatic parsing of an XML file.
We illustrate the mechanism using the GModelSpectralRegistry
class. Here an excerpt of the class definition:
class GModelSpectralRegistry { public: GModelSpectralRegistry(const GModelSpectral* model); GModelSpectral* alloc(const std::string& type) const; private: static int m_number; //!< Number of models in registry static std::string* m_names; //!< Model names static const GModelSpectral** m_models; //!< Pointer to seed models };All class members are static, so that every instance of the class gives access to the same data. The static variables are initialised in
GModelSpectralRegistry.cpp
:int GModelSpectralRegistry::m_number(0); std::string* GModelSpectralRegistry::m_names(0); const GModelSpectral** GModelSpectralRegistry::m_models(0);
m_number
counts the number of derived classes that are registered, m_names
points to a vector of string elements that contain the unique names of the derived classes, and m_models
are pointers to instances of the different derived classes. These instances are also called the seeds.
The central method of the GModelSpectralRegistry
class is the alloc()
method. This method allocates a new instance of a derived class using the unique name of the class. For example, by specifying
GModelSpectralRegistry registry; GModelSpectral* spectral = registry("PowerLaw");the pointer
spectral
will hold an instance of GModelSpectralPlaw
. This is achieved by searching the array of m_names
, and if a match is found, cloning the seed instance:GModelSpectral* GModelSpectralRegistry::alloc(const std::string& type) const { GModelSpectral* model = NULL; for (int i = 0; i < m_number; ++i) { if (m_names[i] == type) { model = m_models[i]->clone(); break; } } return model; }If the requested model is not found,
NULL
is returned.
A spectral model is registered to the registry by adding two global variables at the top of the corresponding .cpp
file. Here the example for GModelSpectralPlaw.cpp
:
const GModelSpectralPlaw g_spectral_plaw_seed; const GModelSpectralRegistry g_spectral_plaw_registry(&g_spectral_plaw_seed);The first line allocates one instance of the class, and the second line stores the address of this instance in the registry using a registry constructor.