Jump to content
  • Advertisement
Sign in to follow this  
MARS_999

C++ array and polymorphic objects

This topic is 2370 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am wondering how could you code something like this with a C style array, without making it into a vector container? I am assuming it isn't possible?


class Obj3D
{
public:
std::string id;
explicit Obj3D(const std::string& name)
{
id = name;
}
virtual ~Obj3D(){}
virtual void Draw(void) = 0;
};
class Mesh : public Obj3D
{
public:
explicit Mesh(const std::string& name) : Obj3D(name){}
virtual ~Mesh(){}
virtual void Draw(void)
{
std::cout << id << std::endl;
}
};
class Cube : public Obj3D
{
public:
explicit Cube(const std::string& name) : Obj3D(name){}
virtual ~Cube(){}
virtual void Draw(void)
{
std::cout << id << std::endl;
}
};
class Sphere : public Obj3D
{
public:
explicit Sphere(const std::string& name) : Obj3D(name){}
virtual ~Sphere(){}
virtual void Draw(void)
{
std::cout << id << std::endl;
}
};


Now I want to make one array that holds all various derived objects....


//now place each object into array? I can't see how you can allocate these after you already allocated 1000 for Obj3D* pointers...

Obj3D* p = new Obj3D[1000];[/font]// I am sure this isn't going to work....
for(int i = 0; i < 1000; ++i)
p = new Mesh();//or cube, sphere... or worse yet add one at a time...



So with a std::vector I can do this...

std::vector<Obj3D*> objects;
objects.push_back(new Mesh("BLAH"));
objects.push_back(new Sphere("BLAH"));
objects.push_back(new Cube("BLAH"));



then run through the vector and walla...

Thanks....

Share this post


Link to post
Share on other sites
Advertisement
Why on earth would you want to do this?


Obvious problems with using raw arrays aside, you want an array of type Obj3D** - an array of pointers.

Share this post


Link to post
Share on other sites
Following on from what ApochPiQ said, you're pretty much asking for trouble here. Even with a vector

std::vector<Obj3D*> objects;
objects.push_back(new Mesh("BLAH"));
objects.push_back(new Sphere("BLAH"));
objects.push_back(new Cube("BLAH"));


you still have to remember to delete the objects in the vector.

so with an array you'd have something like



Obj3D** objects = new Obj3D*[someValue];
objects[0] = new Mesh("BLAH");
objects[1] = new Sphere("BLAH");
objects[2] = new Cube("BLAH");


but this leads to all kinds of problems. Not only do you have to delete all the objects in your objects array, you have to delete the array itself. and what happens when your array isn't big enough? You'll basically end up re-implementing vector (which essentially does exactly this under the hood).

My advice is to use a boost ptr_vector. This takes care of the clean up for you.

Share this post


Link to post
Share on other sites
Thanks for the replies.

So yeah a array of pointers would be the solution, but I was wondering if a single array type would work and I am getting a NO loud and clear here...

Yeah I know of the issues with deleting all the new'd memory, but I was curios to this problem as it's be awhile since I worked with this kind of code and wasn't sure what the best way to do it was...

What about C++11, is there anything in there, that's built in to solve this?

Thanks again!

Share this post


Link to post
Share on other sites

What about C++11, is there anything in there, that's built in to solve this?

I'm not sure what "solve this" is referring to (the deleting of new'd memory, or the polymorphic behavior you're wanting out of a dynamic array?). Your original question is about doing this with a C-style array, in which case the answer to the question about the automatic deleting of new'd memory is "no," because you have to manually delete the C-style dynamic array. You could create a dynamic array of smart pointers (i.e. std::shared_ptr), so you wouldn't have to manually delete each object before deleting the entire array, but you still have to delete the dynamic array yourself.

You could use a std::vector<std::shared_ptr<Obj3D>> if you don't apply the C-style array constraint, and be free of memory cleanup entirely.

Share this post


Link to post
Share on other sites
In your example, your derived types don't actually add any extra members, so you could ditch C++ polymorphism:struct Obj3D
{
std::string id;
typedef void (FnDraw)(Obj3D*);
FnDraw* draw;
Obj3D(const std::string& id, FnDraw* draw) : id(id), draw(draw) {}
};
void DrawMesh (Obj3D* o) { std::cout << o->id << std::end; }
void DrawCube (Obj3D* o) { std::cout << o->id << std::end; }
void DrawSphere(Obj3D* o) { std::cout << o->id << std::end; }
Obj3D MakeMesh(const std::string& name) { return Obj3D(name,&DrawMesh); }
Obj3D MakeCube(const std::string& name) { return Obj3D(name,&DrawCube); }
Obj3D MakeSphere(const std::string& name) { return Obj3D(name,&DrawSphere); }

Obj3D* p = new Obj3D[1000];
for(int i = 0; i < 1000; ++i)
p = MakeMesh("foo");//or cube, sphere...

Share this post


Link to post
Share on other sites
Hodgman, the example is really bad... I didn't think up of a great usage example when I wrote it... I was mainly looking for some info on how to deal with it, and I have become rusty... Now everyone is talking about it, I think I remember something about this from a long time ago... Thanks! :)

Share this post


Link to post
Share on other sites
I think this would be a more concise example....


const unsigned int SIZE = 3;
Obj3D** objs = new Obj3D*[SIZE];
objs[0] = new Mesh("BLAH");
objs[1] = new Sphere("BLAH");
objs[2] = new Cube("BLAH");
for(unsigned int i = 0; i < SIZE; ++i)
objs->Draw();
for(unsigned int i = 0; i < SIZE; ++i)
delete objs;
delete []objs;


But I think I am going to take a look at the various other method others have suggested...

Thanks

Share this post


Link to post
Share on other sites
There isn't anything wrong with using raw arrays or manual memory management at all. I would strongly suggesting thinking about whether you really need to use anything from the standard library or boost before you actually do.

The answer to you question, as previously stated is to using an array of pointers, you were only allocating an array of objects.

Share this post


Link to post
Share on other sites

There isn't anything wrong with using raw arrays or manual memory management at all. I would strongly suggesting thinking about whether you really need to use anything from the standard library or boost before you actually do.


I would consider this dangerous and unhelpful advice. The reverse should be true: Unless using something from the standard library or Boost is going to cause significant, documentable problems you should use those tools. Admittedly, there are situations where neither of those two will be helpful (like working on some platform with a horribly suboptimal compiler or under extreme resource constraints where you have to count each byte) but this is not the usual case.

Share this post


Link to post
Share on other sites

This topic is 2370 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Guest
This topic is now closed to further replies.
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!