ryantuck
ryantuck

Reputation: 6634

C++ Array of pointers to class names

I'd like to be able to hold an array of class names and simply pass an index to a function which would create an instance of a certain class. I have memory constraints so I'd like to not simply create an array of objects.

Here's my most descriptive pseudo-code:

Classes:

class Shape
{
public:
    Shape();
};

class Square : public Shape
{
public:
    Square();
};

class Triangle : public Shape
{
public:
    Triangle();
};

Main:

int main()
{
    pointerToShapeClass arrayOfShapes[2];       // incorrect syntax - but
    arrayOfShapes[0] = pointerToSquareClass;    // how would i do this?
    arrayOfShapes[1] = pointerToTriangleClass;

    cin << myNumber;

    // Depending on input, create instance of class corresponding to array index
    if (myNumber == 0) { // create Square   instance }
    if (myNumber == 1) { // create Triangle instance }

    return 0;
}

If this is confusing, I can try to elucidate. Thanks in advance!

Edit:

Really, I think I just need a pointer to a class without actually instantiating the class.

Upvotes: 1

Views: 1596

Answers (4)

Joseph Mansfield
Joseph Mansfield

Reputation: 110648

Sounds like you want some kind of factory:

class Shape
{
public:
    Shape();
    static Shape* create(int id);
};

Shape* Shape::create(int id) {
  switch (id) {
    case 0: return new Square();
    case 1: return new Triangle();
  }
  return NULL;
}

Then when you want to create a particular Shape given user input, you can do:

int myNumber;
cin >> myNumber;
Shape* shape = Shape::create(myNumber);

This is it in it's simplest form. I would, however, recommend having the create function return a std::unique_ptr<Shape>, rather than a raw pointer. I would also set up static constants to represent the different IDs.

class Shape
{
public:
    Shape();
    static std::unique_ptr<Shape> create(int id);

    enum class Id { Square = 0, Triangle = 1 };
};

std::unique_ptr<Shape> Shape::create(Shape::Id id) {
  switch (id) {
    case Shape::Id::Square: return new Square();
    case Shape::Id::Triangle: return new Triangle();
  }
  return nullptr;
}

Upvotes: 4

Tony The Lion
Tony The Lion

Reputation: 63190

Create a std::vector<Shape*> and then you can do v.emplace_back(new Triangle()); in C++11. In C++03 you can use v.push_back(new Triangle());

You could use a raw array

Shape* shapes[10]; // array of pointers;

shapes[0] = new Triangle(); 

You could also go to use templates and create a template

template<typename ShapeType>
class Shape
{
 public:
     ShapeType draw(); 
     //All common Shape Operations
};

class Triangle
{
};

//C++11
using Triangle = Shape<Triangle>;
Triangle mytriangle;

//C++03
typedef Shape<Square> Square;
Square mysquare;

Upvotes: 2

Roee Gavirel
Roee Gavirel

Reputation: 19445

I would create this function:

Shape getNewShape(int shapeId)
{
    switch (shapeId)
    {
        case 1: return new Square();
        case 2: return new Triangle();
    }
    //here you should handle wrong shape id
}

then use it like that:

int main()
{
    cin << myNumber;

    // Depending on input, create instance of class corresponding to array index
    shape tempShape = getNewShape(myNumber);

    return 0;
}

Upvotes: 1

Silas
Silas

Reputation: 406

Try this:

int main()
{
    std::vector<Shape*> shapes;

    cin << myNumber;

    // Depending on input, create instance of class corresponding to array index
    if (myNumber == 0) { shapes.push_back(new Square(); }
    if (myNumber == 1) { shapes.push_back(new Triangle(); }

    return 0;
}

Upvotes: 2

Related Questions