2010-10-24 28 views
12

Digamos que tengo una clase caja, y un usuario puede crear cajas. ¿Cómo hacerlo? Entiendo que creo objetos por className objectName(args);, pero ¿cómo hacerlo dinámicamente, dependiendo de la entrada del usuario?¿Cómo crear objetos de clase dinámicamente?

+3

¿Puede dar un ejemplo de código (potencialmente pseudocódigo)? –

+0

¿Creen dónde? Puede almacenarlos en un 'std :: vector', por ejemplo, pero esto realmente depende de lo que esté haciendo. – GManNickG

+0

Desafortunadamente en C++ no se puede llamar dinámicamente a un constructor. La única forma es almacenar objetos que puedan devolver un objeto recién construido de lo que desea en el tiempo de ejecución. Los ejemplos de respuestas que usted ya recibió son completamente relevantes. –

Respuesta

5

El siguiente método de fábrica crea Box casos dinámicamente en base a la entrada del usuario:

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

Por supuesto, PrettyBigBox y SmallBox tanto derivan de Box. Eche un vistazo a los patrones creacionales en el C++ design patterns wikibook, ya que uno de ellos probablemente se aplique a su problema.

2

En C++, es posible asignar objetos utilizando almacenamiento automático (pila) y dinámico (montón).

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. 

Puede usar punteros y de lixiviación en la asignación de construir dinámicamente objetos como en:

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

relacionadas: the "Factory" object-oriented design pattern

15

La respuesta correcta depende del número de clases diferentes de los que desea para crear las instancias.

Si el número es enorme (la aplicación debería poder crear una instancia de cualquier clase en su aplicación), debe usar la funcionalidad de reflexión de .Net. Pero, para ser sincero, no soy un gran admirador de usar la reflexión en la lógica de negocios, así que les aconsejo que no lo hagan.

Creo que en realidad tiene un número limitado en las clases para las que desea crear instancias. Y todas las otras respuestas hacen esta suposición. Lo que realmente necesitas es un patrón de fábrica. En el siguiente código que también asumen que las clases de los que desea crear instancias, todos derivan de la misma clase base, digamos animal, así:

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

A continuación, cree una fábrica abstracta, que es una interfaz que crea un animal:

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

A continuación, cree subclases para cada uno de los diferentes tipos de animales. P.ej. para la clase Dog esto se convertirá en esto:

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

Y lo mismo para el gato.

El método DogFactory :: create anula el método IFactory :: create, incluso si el tipo de devolución es diferente. Esto es lo que se llama tipos de retorno co-variante. Esto está permitido siempre que el tipo de devolución del método de la subclase sea una subclase del tipo de devolución de la clase base.

Lo que ahora se puede hacer es poner los casos de todas estas fábricas en un mapa, así:

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

Después de la entrada del usuario, usted tiene que encontrar la fábrica correcta, y le pedirá que cree la instancia del animal:

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

Este es el enfoque típico de fábrica abstracta. También hay otros enfoques. Cuando me enseñé a C++, escribí un pequeño artículo sobre CodeProject al respecto. Puede encontrarlo aquí: http://www.codeproject.com/KB/architecture/all_kinds_of_factories.aspx.

Buena suerte.

0

Una manera simple es utilizar el vector. primero, incluye la biblioteca de vectores y crea un objeto temporal como clase.

class temp; 

a continuación, hacer un vector, por ejemplo, el nombre de objetos con su tipo de clase:

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

continuación, puede añadir un bucle a la adición de un ejemplo object.for, tengo una llamada temp clase que tiene una función llamada entrada y quiero agregar:

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

ahora usted tiene una clase dinámica. para acceder a los objetos que se pueden utilizar de esta manera:

objects[i]; 

y si desea eliminar un objeto, basta con utilizar de esta manera: 1.Encuentre objeto de su ubicación en el vector. cantidad 2.Cambie del último bloque de su vector con eso y quitar el último bloque:

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

si desea conocer la ubicación del último bloque de su vector ello:

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

nota: puede usar vectores como una matriz.

Cuestiones relacionadas