2012-02-27 7 views
6

Por ejemplo, en la función principal, quiero obtener la entrada del usuario. Según la entrada, crearé Rectangle o Circle, que son clases secundarias de Object. Si no hay datos de entrada (o desconocidos), entonces crearé un objeto genérico.¿Cómo crear instancias de diferentes clases secundarias de forma condicional?

class Object 
{ 
     public: 
      Object(); 
      void Draw(); 
     private: 
      .... 
}; 
class Rectangle:public Object 
{ 
     public: 
      Rectangle(); 
      .... //it might have some additional functions 
     private: 
      .... 
}; 

class Circle:public Object 
{ 
     public: 
      Circle(); 
      .... //it might have some additional functions 
     private: 
      .... 
}; 

función principal:

string objType; 
getline(cin, objType); 

if (!objType.compare("Rectangle")) 
    Rectangle obj; 
else if (!objType.compare("Circle")) 
    Circle obj; 
else 
    Object obj; 

obj.Draw(); 

Por supuesto, el código anterior no funcionará porque no puedo crear una instancia de un objeto dentro de una instrucción If. Así que intenté algo como esto.

Object obj; 
if (!objType.compare("Rectangle")) 
    obj = Rectangle(); 
else if (!objType.compare("Circle")) 
    obj = Circle(); 


obj.Draw(); 

Este código se compilaría, pero no hará lo que yo quiera. Por alguna razón, el objeto no se inició de la misma forma que la clase hija (por ejemplo, establecí las variables miembro de un Objeto, específicamente, un vector, de manera diferente en las clases secundarias). Sin embargo, cuando puse un punto de ruptura en el constructor de la clase Child, se ejecutó allí.

Entonces, ¿cómo debería poner objetos instanciados como sus clases secundarias en algunas sentencias if?

Respuesta

10

Usted puede crear objetos automáticos en if declaraciones, pero serán destruidas al final del alcance que se crean en lo que no funcionan para este problema.

La razón por la que no puede hacer el obj = Rectangle() es por slicing.

Tienes que tener un puntero a un Object. Los punteros a objetos base también pueden apuntar a instancias de objetos secundarios. A continuación, puede crear dinámicamente el objeto dentro de las if con new (objetos creados con alcance new indiferencia y sólo se destruyen cuando se llama a delete en un puntero a ellos), entonces delete que cuando haya terminado:

Object* obj = NULL; // obj doesn't point to anything yet 
string objType; 
getline(cin, objType); 

if (objType == "Rectangle") 
    obj = new Rectangle; // make obj point to a dynamic Rectangle 
else if (objType == "Circle") 
    obj = new Circle; // make obj point to a dynamic Circle 
else 
    obj = new Object; // make obj point to a dynamic Object 

obj->Draw(); // draw whatever shape obj really points to 

delete obj; // deallocate dynamic object 

Alternativamente, puede usar punteros inteligentes y luego no tiene que preocuparse por la desasignación manual del objeto:

std::unique_ptr<Object> obj(NULL); // obj doesn't point to anything yet 
string objType; 
getline(cin, objType); 

if (objType == "Rectangle") 
    obj.reset(new Rectangle); // make obj point to a dynamic Rectangle 
else if (objType == "Circle") 
    obj.reset(new Circle); // make obj point to a dynamic Circle 
else 
    obj.reset(new Object); // make obj point to a dynamic Object 

obj->Draw(); // draw whatever shape obj really points to 

// the unique_ptr takes care of delete'ing the object for us 
// when it goes out of scope 
+0

¡Funciona! Además de la solución a mi problema, gracias por dar una buena explicación de cómo funcionan las clases y el puntero en C+++. – tuzzer

Cuestiones relacionadas