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
Libérer: 2024-12-20 01:33:10
original
1070 Les gens l'ont consulté

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>;
Copier après la connexion

Ensuite, vous pouvez également instancier les objets help:

return map[some_string]();
Copier après la connexion

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");
Copier après la connexion

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)
Copier après la connexion

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;
Copier après la connexion

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!

source:php.cn
Déclaration de ce site Web
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
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal