web-dev-qa-db-fra.com

Comment créer des objets de classe dynamiquement?

Disons que j'ai une classe box et qu'un utilisateur peut créer des boxes . Comment faire? Je comprends que je crée des objets par className objectName(args); mais comment le faire de manière dynamique, en fonction de la saisie de l'utilisateur?

15
Nebort

La réponse correcte dépend du nombre de classes différentes pour lesquelles vous souhaitez créer les instances.

Si le nombre est énorme (l'application doit pouvoir créer une instance de n'importe quelle classe dans votre application), vous devez utiliser la fonctionnalité de réflexion de .Net. Mais, pour être honnête, je ne suis pas un grand partisan de l’utilisation de la réflexion dans la logique d’entreprise, je vous déconseille donc de le faire.

Je pense qu'en réalité, vous avez un nombre limité de classes pour lesquelles vous voulez créer des instances. Et toutes les autres réponses font cette hypothèse. Ce dont vous avez réellement besoin, c'est d'un motif d'usine. Dans le code suivant, je suppose également que les classes dont vous voulez créer des instances proviennent toutes de la même classe de base, disons Animal, comme ceci:

class Animal {...};
class Dog : public Animal {...}
class Cat : public Animal {...}

Créez ensuite une fabrique abstraite qui est une interface créant un animal:

class IFactory
   {
   public:
      Animal *create() = 0;
   };

Créez ensuite des sous-classes pour chacun des différents types d’animaux. Par exemple. pour la classe Dog, cela deviendra:

class DogFactory : public IFactory
   {
   public:
      Dog *create() {return new Dog();}
   };

Et pareil pour le chat.

La méthode DogFactory :: create remplace la méthode IFactory :: create, même si leur type de retour est différent. C'est ce qu'on appelle les types de retour co-variant. Cela est autorisé tant que le type de retour de la méthode de la sous-classe est une sous-classe du type de retour de la classe de base.

Ce que vous pouvez maintenant faire est de mettre des instances de toutes ces usines dans une carte, comme ceci:

typedef std::map<char *,IFactory *> AnimalFactories
AnimalFactories animalFactories;
animalFactories["Dog"] = new DogFactory();
animalFactories["Cat"] = new CatFactory();

Après la saisie de l'utilisateur, vous devez trouver la bonne usine et lui demander de créer l'instance de l'animal:

AnimalFactories::const_iterator it=animalFactories.find(userinput);
if (it!=animalFactories.end())
   {
   IFactory *factory = *it;
   Animal *animal = factory->create();
   ...
   }

C’est l’approche typique des fabriques abstraites Il existe aussi d’autres approches. En enseignant le C++, j’ai écrit un petit article sur CodeProject à ce sujet. Vous pouvez le trouver ici: http://www.codeproject.com/KB/architecture/all_kinds_of_factories.aspx .

Bonne chance.

18
Patrick

La méthode d'usine suivante crée des instances Box de manière dynamique en fonction des entrées de l'utilisateur:

class BoxFactory
{
  public:
    static Box *newBox(const std::string &description)
    {
      if (description == "pretty big box")
        return new PrettyBigBox;
      if (description == "small box")
        return new SmallBox;
      return 0;
    }
};

Bien entendu, PrettyBigBox et SmallBox sont tous deux dérivés de Box. Examinez les modèles de création du modèles de conception C++ wikibook , car l’un d’eux s’applique probablement à votre problème.

5
Ton van den Heuvel

En C++, il est possible d'allouer des objets à l'aide du stockage automatique (pile) et dynamique (tas).

Type variable_name; // variable_name has "automatic" storage.
                    // it is a local variable and is created on the stack.

Type* pointer_name = NULL; // pointer_name is a "pointer". The pointer, itself,
                           // is a local variable just like variable_name
                           // and is also created on the stack. Currently it
                           // points to NULL.

pointer_name = new DerivedType; // (where DerivedType inherits from Type). Now
                                // pointer_name points to an object with
                                // "dynamic" storage that exists on the heap.

delete pointer_name; // The object pointed-to is deallocated.
pointer_name = NULL; // Resetting to NULL prevents dangling-pointer errors.

Vous pouvez utiliser des pointeurs et une allocation de tas pour construire dynamiquement des objets comme dans:

#include <cstdlib>
#include <iostream>
#include <memory>
class Base {
    public:
        virtual ~Base(){}
        virtual void printMe() const = 0;
    protected:
        Base(){}
};
class Alpha : public Base {
     public:
        Alpha() {}
        virtual ~Alpha() {}
        virtual void printMe() const { std::cout << "Alpha" << std::endl; }
};
class Bravo : public Base {
     public:
        Bravo() {}
        virtual ~Bravo() {}
        virtual void printMe() const { std::cout << "Bravo" << std::endl; }
};
int main(int argc, char* argv[]) {
    std::auto_ptr<Base> pointer; // it is generally better to use boost::unique_ptr,
                                 // but I'll use this in case you aren't familiar
                                 // with Boost so you can get up and running.
    std::string which;
    std::cout << "Alpha or bravo?" << std::endl;
    std::cin >> which;
    if (which == "alpha") {
        pointer.reset(new Alpha);
    } else if (which == "bravo") {
        pointer.reset(new Bravo);
    } else {
        std::cerr << "Must specify \"alpha\" or \"bravo\"" << std::endl;
        std::exit(1);
    }
    pointer->printMe();
    return 0;
}

Connexes: le modèle de conception orienté objet "Factory"

3

Une méthode simple consiste à utiliser vecteur , D’abord, incluez une bibliothèque de vecteurs et créez un objet temporaire en tant que classe.

class temp;

créez ensuite un vecteur, par exemple, des objets nommés avec votre type de classe:

#include <vector>
.
.
vector <class>objects;

alors vous pouvez ajouter une boucle pour ajouter un objet. Par exemple, j'ai une classe nommée temp qui a une fonction nommée input et que je veux ajouter:

while(1){
        temp.input();
        objects.Push_back(temp);
        }

vous avez maintenant une classe dynamique. pour accéder à vos objets, vous pouvez utiliser cette méthode:

objects[i];

et si vous souhaitez supprimer un objet, utilisez simplement la méthode suivante: 1.Trouvez la position de votre objet dans le vecteur. dernier bloc:

objects[location of the object you want to remove]=objects[location of your last block];
objects.pop_back();

si vous voulez connaître l'emplacement du dernier bloc de votre vecteur, faites ceci:

int lastblock;
lastblock=(objects.size()-1);

remarque: vous pouvez utiliser des vecteurs comme un tableau.

0
Lost Gost