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.

Also available in: PDF HTML TXT