   OOP: dynamically-sized arrays of base classes
  Hey, I'm working on this object-oriented program and I'm trying dynamically size this array of objects that could possibly be derived from it as a base class. I'm not sure that's very clear, so I'll express it in a code example:GraphicsObject ** object;int objectCount = -1;HRESULT Engine::Add(const GraphicsObject & obj){GraphicsObject ** temp = new GraphicsObject*[objectCount];for (int x=0;x<objectCount;x++){temp[x] = new GraphicsObject;*temp[x] = *object[x];}delete [] object;object = new GraphicsObject*[objectCount+1];for (int x=0;x<objectCount;x++){object[x] = new GraphicsObject;*object[x] = *temp[x];}delete[] temp;}GraphicsObject is the base class for all objects renderable. Because this may not be a GraphicsObject, but another class derived from GraphicsObject, I had to create an array of pointers-to-GraphicsObject. I have found no adequate documentation on arrays of pointers and how to use them in the context.I believe there are other problems with this method, but I haven't found them yet. The real problem I have right now is how to add the final object without making the method parameter a pointer. Any help with this simple problem and any other problems this routine may have will be GREATLY appreciated.Recommendations on how this code should look, or design ideas dealing with the whole method of storing this array will be greatly appreciated.Thank you,~David[Edited by - zeldafreak on January 6, 2006 8:01:53 AM]
  Consider using a std::vector of (smart) pointers instead of manually managing the dynamic arrays. Also consider using boost::ptr_vector instead,   ;  Could provide a little more information about std::vector and boost:ptr_vector? I've never heard of these, where can I find out more about them?   ;  The SGI documentation is good on vectors: clicky.  Also try this tutorial.  Googling for 'std::vector' should yield some good results.I haven't used Boost before so I can't comment on that.   ;Quote:GraphicsObject ** temp = new GraphicsObject*[objectCount];for (int x=0; x<objectCount; x++){  temp[x] = new GraphicsObject;  *temp[x] = *object[x];}If you want to delete all the memory associated with the temp array, you need to do something like this:for (int x=0; x<objectCount; x++)  delete temp[x];delete [] temp;;  okay, so now I'm using vector to handle the dynamic array, but there's still a problem.I have to do std::vector<GraphicsObject*>, because they have to pointers-to-GraphicsObject because they be derived classes from that base type. However, how do I add a pointer to a temporary variable passed into the Add() method?Here:vector<GraphicsObject*> object;void Engine::Add(const GraphicsObject & add);How do I add that object to the vector of pointer-to-GraphicsObjects?I guess I could do this:vector<GraphicsObject*> object;void Engine::Add(GraphicsObject * add);The problem is that the pointer could point to data that will be freed eventually. Or am I wrong?EDIT:object.pushback(add) will create an error, right? Because that pointer will be invalidated at the end of the code block?[Edited by - zeldafreak on January 6, 2006 8:57:01 AM];  If you are wondering how to add objects onto a vector you can use the push_back() or push_front() member functions push_back() pushes an object onto the back of the vector while push_front() pushes it on the front likevector<int> val;for(int i =0; i < 12; i++){  val.push_back(i); // push 1 on the back of our vector  cout << val << " "; // output value}// should output // now lets push them onto the front of itfor(int i =0; i < 12; i++){  val.push_front(i);  cout << val << " ";}// should output if i remember correctly 12 11 10 9 8 7 6 5 4 3 2 1 0 0 1 2 3 4 5 6 7 8 9 10 11 12So another thing you can also do is add objects into a vector like#include <iostream>#include <vector>using namespace std;class test{  int i;  public:  int returnI() { return i; }  void Add(int val) { i = val; }};int main(){  vector<test*> cls(10); // make a dynamic array of 10 object pointer  for(int i = 0; i < cls.size(); i++)  {   cls->Add(i); // add i  }  for(int i = 0; i < cls.size; i++)  {   cout << cls->returnI() << " ";  }  return 0;}I aint sure if that works but i think it will i havn't done C++ for a few weeks now but i hope i helped.[Edited by - GameMasterXL on January 6, 2006 9:41:41 AM];Quote:object.pushback(add) will create an error, right? Because that pointer will be invalidated at the end of the code block?If the object that "add" points to is local or temporary, yes.void Engine::Add(const GraphicsObject & add){  GraphicsObject* temp = new GraphicsObject;  *temp = add;  vec.push_back(temp);}...// If you dont use smart pointers, I believe you need to delete each vector item yourself...for(int i=0; i<vec.size(); i++)  delete vec;;  but wait wouldn't the delete vec; not work since delete requires the [] to be infront of it like delete[]. So would it be delete vec?;Quote:Original post by zeldafreakokay, so now I'm using vector to handle the dynamic array, but there's still a problem.I have to do std::vector<GraphicsObject*>, because they have to pointers-to-GraphicsObject because they be derived classes from that base type. However, how do I add a pointer to a temporary variable passed into the Add() method?Here:vector<GraphicsObject*> object;void Engine::Add(const GraphicsObject & add);There's no temporary variable there; that's rather the point of passing by (const) reference. You would just .push_back(&add) here (note the & sign; when you pass by reference you work syntactically *as if* you had a value, therefore you need to take the address of it to yield a pointer to that object). That appends to the vector a pointer that points to the passed-in object.If that object then goes out of scope in the calling function, then yes, you are screwed. The vector would then contain a pointer to invalid memory. Similarly, if you delete the pointer from the vector, then the memory is freed, and attempting to destruct the same object from outside (either by letting it fall out of scope or by deleting it from outside) results in a double deletion.What you need is to have a (design) policy about who "owns" the object. The easiest and normally best way to handle this is to use a wrapper object that implements the policy - for example, boost::shared_ptr. You could also use one of the Boost "pointer containers" like ptr_vector as well.Basically, listen to SiCrane. :)   