[c++] class register

Description

Permet de garder une trace de toutes les classes crees.

J'ai fais ce code a la base car j'utilise souvent Qt et les connections ne peuvent etre faites que en aillant les pointeurs sur les classes que l'on veut connecter.
Cette methode est un peu genante lors de gros projets (enfin a mon gout), ou il est dur de voir quelle classe est connectee a telle autre sachant que les connections sont faites un peu partout.
Maintenant de n'importe ou dans le code on peut connecter des classes sans avoir a garder un pointeur sur celles ci, ou les isoler dans une classe qui s'occupera de faire seulement des connections par exemple.

Le but de ce code n'est absolument pas de servir de garbage collector, et encore moins de servir pour autre chose que ce qu'il a ete prevu. En revanche on peut s'en servir pour voir le nombre de classes de tel ou tel type crees, faire des stats... tant qu'il n'y a pas d'interaction forte avec votre code qui le ferait dependre entierement de ce systeme.

Utilisation:

Pour enregister une classe la macro CR_REGISTER(class) ou "class" est le nom de votre classe est a utiliser dans le constructeur.
La macro CR_UNREGISTER(class) est quand a elle utilisee dans le destructeur.

Des macros servent ensuite a recuperer les instances de classes qu'on a enregistre, a partir de n'importe ou dans le code
CR_GETFIRST(class) retourne la premiere instance de "class" trouvee
CR_GETALL(class) retourne un std::vector contenant tous les pointeurs sur les "class" enregistrees
CR_FOREACH(class) itere sur toutes les instances de "class", le pointeur se recupere avec CR_p

La sortie du main ci dessous est affichee sur le screenshot.

Source / Exemple :


// ======================== ClassRegister =========================
// Description: Do useless things, but do it well
// Made by: Remi Bourreau AKA Miwik
// Contact: miwikprog@gmail.com
// Rights: You can do what you want with this lol code :)
// ================================================================

#include <iostream>
#include <sstream>
#include <iomanip>

#include "ClassRegister.h"

// this class is used only to avoid copy of code in the test classes like operator << overload.
// display the creation and destruction with an identifier, nothing special here.
class Example
{
public:
    Example(std::string strName) : _strName(strName), _id(++id)
    {
        std::ostringstream oss;

        std::cout << "Creation    <= " << _strName << std::setw(10 - _strName.size()) << _id << std::endl;
        oss << "Heya im " << strName << "!" << std::setw(16 - _strName.size()) << _id;
        _strWho = oss.str();
    }
    virtual ~Example() { std::cout << "Destruction => " << _strName << std::setw(10 - _strName.size()) << _id << std::endl; }

    inline friend std::ostream &operator <<(std::ostream &os, Example &Example) { return os << Example.Who(); }
    inline virtual std::string Who() const { return _strWho; }

protected:
    static int id;

private:
    std::string _strName;
    std::string _strWho;
    int _id;
};

int Example::id = -1;

// macro CR_REGISTER(type) must be used in the constructor to register the class,
// if not you wont be able to access your class later.
// macro CR_UNREGISTER(type) must be used in the destructor to unregister the class,
// if not you will have some cool segfaults when trying to access an already deleted class.
class One : public Example
{
public:
    One() : Example("One") { CR_REGISTER(One); }
    virtual ~One() { CR_UNREGISTER(One); }
};

// same here
class Two : public Example
{
public:
    Two() : Example("Two") { CR_REGISTER(Two); }
    virtual ~Two() { CR_UNREGISTER(Two); }
};

// another one
class Tree : public Example
{
public:
    Tree() : Example("Tree") { CR_REGISTER(Tree); }
    virtual ~Tree() { CR_UNREGISTER(Tree); }
};

// without call to macros
class Hey : public Example
{
public:
    Hey() : Example("Hey") {}
    virtual ~Hey() {}
};

// show how to get the objects registered with the macro
// the macros CR_* can be use everywhere in your code
int main()
{
    One *o0 = new One; // id 0
    One o1;            // id 1
    Two *t2 = new Two; // id 2
    One o3;            // id 3
    One *o4 = new One; // id 4
    Two t5;            // id 5
    Tree e6;           // id 6
    Hey ho;

    std::cout << "\nCR_GETFIRST One" << std::endl;
    One *one = CR_GETFIRST(One);
    if (one)
        std::cout << *one << std::endl;

    std::cout << "\nCR_GETFIRST Two" << std::endl;
    Two *two = CR_GETFIRST(Two);
    if (two)
        std::cout << *two << std::endl;

    // call of a non registered object
    Hey *hey = CR_GETFIRST(Hey);
    if (hey)
        std::cout << "wtf ? o.O  " << *hey << std::endl;

    delete o0; // delete test

    std::cout << "\nCR_FOREACH  One" << std::endl;
    CR_FOREACH(One)
    {
        std::cout << *CR_p << std::endl;
    }

    std::cout << "\nCR_FOREACH  Two" << std::endl;
    CR_FOREACH(Two)
            std::cout << *CR_p << std::endl;

    delete t2;
    delete o4;

    CR_KILL;

    return 0;
}

Conclusion :


<(o.O)>

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.