Maison >développement back-end >C++ >Comment créer des objets C à partir d'une chaîne contenant leur nom de classe ?

Comment créer des objets C à partir d'une chaîne contenant leur nom de classe ?

Patricia Arquette
Patricia Arquetteoriginal
2024-12-20 01:33:101068parcourir

How to Create C   Objects from a String Containing Their Class Name?

Comment instancier des objets à partir d'une chaîne contenant leur nom de classe ?

Dans le code donné, une classe BaseFactory crée des objets de différentes classes dérivées basé sur une chaîne représentant leur nom de classe. Cependant, l'usine exige l'ajout manuel d'instructions if pour chaque classe dérivée possible. On peut se demander s'il existe une alternative à cette approche verbeuse, similaire à la fonctionnalité Reflection de C#.

malheureusement il n'y a pas de mécanisme automatisé

Malheureusement, C n'a pas de mécanisme pour les objets de création automatique des types spécifiés au moment de l'exécution. Cependant, il est possible de faire le mappage vous-même :

Mappage de types

Vous pouvez créer une carte qui stocke, pour chaque nom de classe, une fonction qui crée un objet de cette classe :

template<typename T> Base * createInstance() { return new T; }

typedef std::map<std::string, Base*(*)()> map_type;

map_type map;
map["DerivedA"] = &amp;createInstance<DerivedA>;
map["DerivedB"] = &amp;createInstance<DerivedB>;

Ensuite, vous pouvez également instancier les objets help:

return map[some_string]();

Enregistrement des types

Une solution alternative consiste à permettre aux types de s'enregistrer eux-mêmes :

// w base.hpp:
template<typename T> Base * createT() { return new T; }

struct BaseFactory {
    typedef std::map<std::string, Base*(*)()> map_type;

    static Base * createInstance(std::string const&amp; s) {
        map_type::iterator it = getMap()->find(s);
        if(it == getMap()->end())
            return 0;
        return it->second();
    }

protected:
    static map_type * getMap() {
        // nigdy nie usuwane (istnieje do zakończenia programu)
        // ponieważ nie możemy zagwarantować poprawnej kolejności usuwania
        if(!map) { map = new map_type; }
        return map;
    }

private:
    static map_type * map;
};

template<typename T>
struct DerivedRegister : BaseFactory {
    DerivedRegister(std::string const&amp; s) {
        getMap()->insert(std::make_pair(s, &amp;createT<T>));
    }
};

// w derivedb.hpp
class DerivedB {
    ...;
private:
    static DerivedRegister<DerivedB> reg;
};

// w derivedb.cpp:
DerivedRegister<DerivedB> DerivedB::reg("DerivedB");

Vous pouvez également définir des macros pour l'enregistrement de type :

#define REGISTER_DEC_TYPE(NAME) \
    static DerivedRegister<NAME> reg

#define REGISTER_DEF_TYPE(NAME) \
    DerivedRegister<NAME> NAME::reg(#NAME)

Pour les types qui ne partagent pas une classe de base commune, vous pouvez utiliser la variante boost::variant comme type de retour de fonction:

typedef boost::variant<Foo, Bar, Baz> variant_type;
template<typename T> variant_type createInstance() {
    return variant_type(T());
}

typedef std::map<std::string, variant_type (*)()> map_type;

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn