2010-10-24 5 views
12

Disons que j'ai une classe boîte, et un utilisateur peut créer boîtes. Comment faire? Je comprends que je crée des objets par className objectName(args); mais comment le faire dynamiquement, en fonction de l'entrée de l'utilisateur?Comment créer des objets de classe dynamiquement?

+3

Pouvez-vous donner un exemple de code (potentiellement pseudocode)? –

+0

Créez-les où? Vous pouvez les stocker dans un 'std :: vector', par exemple, mais cela dépend vraiment de ce que vous faites. – GManNickG

+0

Malheureusement, en C++, vous ne pouvez pas appeler dynamiquement un constructeur. Le seul moyen est de stocker des objets qui sont capables de retourner un objet construit frais de ce que vous voulez à l'exécution. Les exemples de réponses que vous avez déjà reçus sont tout à fait pertinents. –

Répondre

5

La méthode usine suivante crée Box instances dynamiquement en fonction de l'entrée 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 sûr, PrettyBigBox et SmallBox proviennent en effet du Box. Jetez un oeil sur les modèles de création dans le C++ design patterns wikibook, comme l'un d'entre eux s'applique probablement à votre problème.

2

En C++, il est possible d'allouer des objets en utilisant le 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 des tas d'allocation 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: the "Factory" object-oriented design pattern

15

La réponse dépend du nombre de classes différentes dont vous voulez pour créer les instances.

Si le nombre est énorme (l'application doit être capable de créer une instance de n'importe quelle classe de votre application), vous devez utiliser la fonctionnalité de réflexion de .Net. Mais, pour être honnête, je ne suis pas un grand fan de l'utilisation de la réflexion dans la logique métier, donc je conseillerais de ne pas 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 modèle d'usine. Dans le code suivant, je suppose aussi que les classes dont vous souhaitez créer des instances, dérivent toutes de la même classe de base, disons que des animaux, comme ceci:

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

Ensuite, créez une usine abstraite qui est une interface crée un animal:

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

Ensuite, créez des sous-classes pour chacun des différents types d'animaux. Par exemple. pour la classe Chien ceci deviendra ceci:

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

Et pareil pour le chat.

La méthode DogFactory :: create écrase la méthode IFactory :: create, même si leur type de retour est différent. C'est ce que l'on appelle les types de retour co-variant. Ceci 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 faire est de cas mettre 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 l'entrée d'utilisateur, vous devez trouver l'usine correcte, 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(); 
    ... 
    } 

Ceci est l'approche typique d'une usine abstraite. Il existe également d'autres approches. En m'enseignant C++ j'ai écrit un petit article de CodeProject à ce sujet. Vous pouvez le trouver ici: http://www.codeproject.com/KB/architecture/all_kinds_of_factories.aspx.

Bonne chance.

0

Une manière simple consiste à utiliser un vecteur. d'abord, incluez la bibliothèque de vecteurs et créez un objet temporaire en tant que classe.

class temp; 

puis, faire un vecteur par exemple des objets nommés avec votre type de classe:

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

vous pouvez ajouter une boucle à ajouter un exemple object.for, j'ai une classe qui a nommé temp une fonction nommée entrée et je veux ajouter:

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

maintenant vous avez une classe dynamique. pour accéder à vos objets, vous pouvez utiliser cette façon:

objects[i]; 

et si vous voulez supprimer un objet, il suffit d'utiliser de cette façon: 1.Find votre position d'objet dans le vecteur. montant 2.CHANGER du dernier bloc de votre vecteur avec qui et retirez le 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 faire:

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

note: vous pouvez utiliser des vecteurs comme un tableau.

Questions connexes