Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to instantiate different child classes conditionally?

For example, in the main function, I want to get the user's input. Depending on the input, I will create either a Rectangle or a Circle, which are child classes of Object. If there's no input (or unknown), then I will just create a generic object.

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

main function:

string objType;
getline(cin, objType);

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

obj.Draw();

Of course, the code above won't work because I can't instantiate an object inside an If statement. So i tried something like this.

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


obj.Draw();

This code would compile, but it won't do what I want. For some reason, the object was not initiated the way the child class should (for example, I set the some Object's member variables, specifically, a vector, differently in the child classes). However, when I put a break point at the Child class constructor, it did run through there.

So how should I put instantiate Objects as its child classes in some if-statements??

like image 425
tuzzer Avatar asked Feb 27 '12 02:02

tuzzer


1 Answers

You can create automatic objects in if statements, but they will be destroyed at the end of the scope they are created in so they don't work for this problem.

The reason you can't do the obj = Rectangle() one is because of slicing.

You have to have a pointer to an Object. Pointers to base objects can also point to instances of child objects. Then you can dynamically create the object inside the if with new (objects created with new disregard scope and are only destroyed when you call delete on a pointer to them), then delete it when you're done:

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

Alternatively, you can use smart pointers and then you don't have to worry about manually deallocating the object:

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
like image 90
Seth Carnegie Avatar answered Sep 23 '22 02:09

Seth Carnegie