Creating a correct subclass via copying.

1
2
3
4
5
6
7
8
enum objectIndex{
	OBJECT_PLAYER,
	MAX_OBJECTS
};

void initObjectList(){
	objList.obj[OBJECT_PLAYER] = new RootComposite();
}

1
2
3
4
5
6
GameObject* createInstance(float x, float y, int index){
	GameObject* obj = new GameObject(*objList.obj[index]);
	obj->create(x,y);
	addNewObject(obj);
	return obj;
}


Currently, I am trying to find a way to easily create an instance without instantiating them using "new". I want to be able to create an instance by just calling the createInstance method above.

First, I will initialized all of the possible objects that I can create and store them in an array. Using enum, I can refer to these arrays and try to copy the already existed object, and return the instance (which is a clone) that I want.

The thing is this: I do not know how to do this properly. You can see this line...
 
GameObject* obj = new GameObject(*objList.obj[index]);

The problem is all of my other game object classes are inherited from the GameObject class. Because I am creating a new (superclass) GameObject, not the actual subclass instance, I cannot refer to the overriden methods at all. This is causing me troubles.

Any advice on how to deal with this? There should be a way to copy an instance in a 100% identical way, or...is it impossible?
Last edited on
Something like this?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Parent
{
virtual Parent* clone() { return new Parent(*this); }
};

class Child
{
virtual Child* clone() { return new Child(*this); }
};

void func(Child* p)
{
  Child* acopy = p->clone();
}


Making clone virtual like that allows you to call derived class's clone function to create a full copy with just a Parent* pointer.

You can make createInstance a template which returns the desired pointer type (rather than a type to the parent class). To downcast from Parent* to Child*, you can use static_cast or dynamic_cast:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// assume Child is derived from GameObject

template <typename T>
T* createInstance(float x,float y,int index)
{
  GameObject* obj = objList.obj[index]->clone();
  obj->create(x,y);
  addNewObject(obj);
  return dynamic_cast<T*>(obj);  // or static_cast<T*> -- see below
}

void blah()
{
  Child* c = createInstance<Child>(x,y,index);
}


Or you can skip the template and put the cast outside the function call:

1
2
3
4
5
6
7
GameObject* createInstance(float x,float y,int index)
{ ... }

void blah()
{
  Child* c = dynamic_cast<Child*>(createInstance(x,y,index));
}



static_cast "downcasts" to derived types forcibly (provided the Child class is in fact derived from the Parent class). It does not do any runtime checks as to whether or not the object actually is a Child.

dynamic_cast does runtime checks to ensure that the pointer conversion is legit (makes sure the pointer actually points to a Child). If it fails, dynamic_cast returns a null pointer. Note that static_cast will never fail, and the resulting bad cast can be potentially devestating!

So dynamic_cast is safer, but more computationally expensive. Probably stick to dynamic_cast unless you're 100% sure you're casting to the object's real type... in which case you can use static_cast
Topic archived. No new replies allowed.