it-swarm.com.de

Wie erstelle ich dynamisch Klassenobjekte?

Angenommen, ich habe eine Klasse box , und ein Benutzer kann boxes erstellen. Wie es geht? Ich verstehe, dass ich Objekte mit className objectName(args); erstelle, aber wie geht das dynamisch, abhängig von der Benutzereingabe?

15
Nebort

Die richtige Antwort hängt von der Anzahl der verschiedenen Klassen ab, von denen Sie die Instanzen erstellen möchten.

Wenn die Anzahl sehr groß ist (die Anwendung sollte in der Lage sein, eine Instanz einer Klasse in Ihrer Anwendung zu erstellen), sollten Sie die Reflection-Funktion von .Net verwenden. Um ehrlich zu sein, bin ich kein großer Fan von Reflexion in der Geschäftslogik. Ich würde daher raten, dies nicht zu tun.

Ich denke, dass Sie in der Realität eine begrenzte Anzahl von Klassen haben, für die Sie Instanzen erstellen möchten. Und alle anderen Antworten stützen diese Annahme. Was Sie tatsächlich brauchen, ist ein Fabrikmuster. Im nächsten Code gehe ich außerdem davon aus, dass die Klassen, von denen Sie Instanzen erstellen möchten, alle von derselben Basisklasse stammen, beispielsweise Animal:

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

Dann erstellen Sie eine abstrakte Fabrik, die eine Schnittstelle ist, die ein Tier erstellt:

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

Erstellen Sie dann Unterklassen für die verschiedenen Tierarten. Z.B. Für die Hundeklasse wird dies Folgendes:

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

Und das gleiche für die Katze.

Die DogFactory :: create-Methode überschreibt die IFactory :: create-Methode, auch wenn ihr Rückgabetyp unterschiedlich ist. Dies ist, was als co-variante Rückgabetypen bezeichnet wird. Dies ist zulässig, solange der Rückgabetyp der Methode der Unterklasse eine Unterklasse des Rückgabetyps der Basisklasse ist.

Was Sie jetzt tun können, ist, Instanzen all dieser Fabriken auf eine Karte zu setzen:

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

Nach der Benutzereingabe müssen Sie die richtige Fabrik finden und sie auffordern, die Instanz des Tieres zu erstellen:

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

Dies ist der typische Ansatz der abstrakten Fabrik. Es gibt auch andere Ansätze. Als ich mir selbst C++ beibrachte, schrieb ich einen kleinen Artikel über CodeProject. Sie finden es hier: http://www.codeproject.com/KB/architecture/all_kinds_of_factories.aspx .

Viel Glück.

18
Patrick

Die folgende Factory-Methode erstellt Box-Instanzen dynamisch basierend auf Benutzereingaben:

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;
    }
};

Natürlich sind PrettyBigBox und SmallBox beide von Box abgeleitet. Werfen Sie einen Blick auf die kreativen Muster im C++ - Entwurfsmuster wikibook , da eines davon wahrscheinlich auf Ihr Problem zutrifft.

5

In C++ können Objekte mithilfe der automatischen (Stapel-) und dynamischen (Heap-) Speicherung zugeordnet werden.

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.

Sie können Zeiger und Heap-Zuordnungen verwenden, um Objekte dynamisch wie folgt zu konstruieren:

#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;
}

Verwandte: das objektorientierte Entwurfsmuster "Factory"

Ein einfacher Weg ist die Verwendung von vector. . Zuerst fügen Sie die Vektorbibliothek ein und erstellen Sie ein temporäres Objekt als Klasse.

class temp;

erstellen Sie dann einen Vektor für benannte Objekte mit Ihrem Klassentyp:

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

dann können Sie eine Schleife hinzufügen, um ein object hinzuzufügen. Zum Beispiel habe ich eine Klasse namens temp, die eine Funktion namens input hat und ich hinzufügen möchte:

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

jetzt haben Sie eine dynamische Klasse. , um auf Ihre Objekte zuzugreifen, die Sie folgendermaßen verwenden können:

objects[i];

und wenn Sie ein Objekt löschen möchten, verwenden Sie einfach diesen Weg: 1. Finden Sie Ihren Objektstandort im Vektor. 2. Ändern Sie die Menge des letzten Blocks Ihres Vektors damit und entfernen Sie das letzter Block:

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

wenn Sie wissen möchten, wo sich der letzte Block Ihres Vektors befindet, gehen Sie folgendermaßen vor:

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

hinweis: Sie können Vektoren wie ein Array verwenden.

0
Lost Gost