Załóżmy, że mam pudełko klasy , a użytkownik może utworzyć skrzynki . Jak to zrobić? Rozumiem, że tworzę obiekty przez className objectName(args);
, ale jak to zrobić dynamicznie, w zależności od danych wejściowych użytkownika?Jak dynamicznie tworzyć obiekty klas?
Odpowiedz
Poniższa metoda fabryka tworzy Box
instancje dynamicznie w oparciu o dane wprowadzone przez użytkownika:
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;
}
};
oczywiście PrettyBigBox
i SmallBox
zarówno wywodzących Box
. Spójrz na schematy kreacji w C++ design patterns wikibook, ponieważ jeden z nich prawdopodobnie dotyczy Twojego problemu.
W C++ możliwe jest przydzielanie obiektów przy użyciu pamięci automatycznej (stos) i dynamicznej (sterty).
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.
Można użyć wskazówki i sterty alokacji dynamicznie budować obiekty jak w:
#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;
}
Prawidłowa odpowiedź zależy od wielu różnych klas, z których chcesz tworzyć instancje.
Jeśli liczba jest ogromna (aplikacja powinna być w stanie utworzyć wystąpienie dowolnej klasy w aplikacji), należy użyć funkcji odbicia .Net. Ale szczerze mówiąc, nie jestem wielkim fanem używania refleksji w logice biznesowej, więc radziłbym tego nie robić.
Myślę, że w rzeczywistości masz ograniczoną liczbę na zajęciach, dla których chcesz utworzyć instancje. I wszystkie inne odpowiedzi przyjmują to założenie. To, czego naprawdę potrzebujesz, to wzór fabryczny. W następnym kodem Zakładam również, że zajęcia z których chcesz utworzyć instancje, wszystkie wywodzą się z tej samej klasy bazowej, powiedzmy zwierząt, podobnie jak to:
class Animal {...};
class Dog : public Animal {...}
class Cat : public Animal {...}
Następnie utwórz abstrakcyjny fabryki, która jest interfejs, który tworzy zwierzę:
class IFactory
{
public:
Animal *create() = 0;
};
Następnie utwórz podklasy dla każdego z różnych gatunków zwierząt. Na przykład. dla klasy Dog stanie się to:
class DogFactory : public IFactory
{
public:
Dog *create() {return new Dog();}
};
Tak samo dla kota.
Metoda DogFactory :: create zastępuje metodę IFactory :: create, nawet jeśli ich typ powrotu jest inny. To jest to, co nazywa się typami zwrotu co-variant. Jest to dozwolone, o ile typ zwracanej metody podklasy jest podklasą typu zwracanego klasy bazowej.
Co można teraz zrobić, to umieścić instancje tych wszystkich fabrykach w mapy, takich jak to:
typedef std::map<char *,IFactory *> AnimalFactories
AnimalFactories animalFactories;
animalFactories["Dog"] = new DogFactory();
animalFactories["Cat"] = new CatFactory();
Po wejściu użytkownika, trzeba znaleźć odpowiednie fabryki, i poprosić go, aby utworzyć instancję zwierzęcia:
AnimalFactories::const_iterator it=animalFactories.find(userinput);
if (it!=animalFactories.end())
{
IFactory *factory = *it;
Animal *animal = factory->create();
...
}
Jest to typowe podejście do abstrakcyjnej fabryki. Istnieją również inne podejścia. Podczas uczenia się w C++ napisałem o tym mały artykuł CodeProject. Można go znaleźć tutaj: http://www.codeproject.com/KB/architecture/all_kinds_of_factories.aspx.
Powodzenia.
Prostym sposobem jest użycie wektora. najpierw umieść bibliotekę wektorową i utwórz tymczasowy obiekt jako swoją klasę.
class temp;
następnie dokonać wektor na przykład o nazwie typu obiektów z klasy:
#include <vector>
.
.
vector <class>objects;
następnie można dodać pętlę do dodawania object.for przykład, mam klasę o nazwie temp, który ma funkcja o nazwie input i chcę dodać:
while(1){
temp.input();
objects.push_back(temp);
}
teraz masz klasę dynamiczną. , aby uzyskać dostęp do swoich obiektów można korzystać w ten sposób:
objects[i];
i jeśli chcesz usunąć obiekt, wystarczy użyć w ten sposób: 1.find swoją lokalizację obiektu w wektorze. ilość 2.change ostatniego bloku swojego wektora z tego i usunąć ostatni blok:
objects[location of the object you want to remove]=objects[location of your last block];
objects.pop_back();
jeśli chcesz znać lokalizację ostatniego bloku swojego wektora zrobić:
int lastblock;
lastblock=(objects.size()-1);
uwaga: możesz używać wektorów takich jak tablica.
Czy możesz podać przykład kodu (potencjalnie pseudokodowego)? –
Utwórz je w miejscu? Możesz na przykład przechowywać je w 'std :: vector', ale to naprawdę zależy od tego, co robisz. – GManNickG
Niestety w języku C++ nie można dynamicznie wywoływać konstruktora. Jedynym sposobem jest przechowywanie obiektów, które są w stanie zwrócić świeżo skonstruowany obiekt tego, co chcesz w środowisku wykonawczym. Przykłady odpowiedzi, które już otrzymałeś, są całkowicie trafne. –