Polymorphism and Copy Constructors

Started by
5 comments, last by Slyfox 14 years ago
Hi, my problem seems as difficult to explain as it is to solve, but I'll give it a try... I have a class within my code called Model that deals with creating 3D models from .x files. From this I have derived the class AnimatedPlaneModel which allows multiple texture to be loaded for a model and displayed to allow animation at a 2D level. Ok In my main code I have a class called GameEntity from which all games objects are derived. GameEntity contains a pointer to a Model object called m_pModel, which is used in the function to LoadModel load a model. m_pModel = new Model(); From GameEntity I have then derived the class Animal this class overrides the LoadModel function of GameEntity and uses polymorphism to make m_pModel point to an AnimatedPlaneModel instead. m_pModel = new AnimatedPlaneModel(); Hopefully explained that ok, now the problem occurs when I later derive a class from Animal called Spider. I create a spider object without object, but next I want to create an array of spiders and copy the data from that first spider into the elements in the array and this is where the copy constructors come into effect. I have written a copy constructor into Animal that looks like the following

	//  Copy Constructor
	Animal(const Animal & rhs)
	{
		m_fAnimationRate = rhs.m_fAnimationRate;
		m_fHeadingAngle = rhs.m_fHeadingAngle;
		m_fSpeed = rhs.m_fSpeed;
		m_vTargetVector = rhs.m_vTargetVector;
		m_pModel = new Model(*rhs.m_pModel);	//  Create a seperate model for the animal 
		                                                                //  in a new memory location but copy all the                                                                        //  data across
	}
This works as it then calls the copy constructor of the model class and copies all the data, but I have realised that I have lost my animated texture data and all the spiders look the same, so instead I tried replacing the line

m_pModel = new Model(*rhs.m_pModel);

//with this line
m_pModel = new AnimatedPlaneModel(*rhs.m_pModel);

I figured this would first call the copy constructor of the AnimatedPlaneModel store the animated texture data and then call the model copy constructor, however visual studio complains that *rhs.m_pModel is of type model not AnimatedPlaneModel despite the fact that it is pointing to an AnimatedPlaneModel and this is where I am stuck. I have tried casting but to no avail. Sorry if this very long winded but I hoped by writing it out it might help me clarify it in my own head. Any help would be much appreciated! Cheers.
Advertisement
Copy constructor is conceptually incompatible with polymorphism. While it can be implemented, it leads to nonsensical situations:
A * a = new A(B);
This makes sense only if A and B are of exactly same type.


Usual solution to this is cloning, which is not without its problems:
A * a = b.clone();
Here, b creates a copy of same type, that will be known as a. The crucial part is that transfers creation of new instance from caller to instance. This solves the problem having to match the types.

clone() is virtual function, implemented by every inherited type. There are likely to be issues with concrete types and inherited clone might need to be called in some way or another.

Copy constructor can then be used to simplify the above process (we now know that A and B are of same type):
Base * Foo::clone() {  Base * copy = new Foo(*this); // copy constructor, we know that 'this' is Foo  return copy;};
I kind of understand what you are saying but am still running into the same issue. I tried creating a clone function in model and animatedplane model but when I try to use it, it again complains that it cannot convert parameter 1 from *Model to AnimatedPlaneModel*. Could please try and clarify how you would used the clone function,

cheers!

Oh btw wikipedia describes my problem as being a result of slicing

http://en.wikipedia.org/wiki/Object_slicing
Quote:Original post by Slyfox
Oh btw wikipedia describes my problem as being a result of slicing

http://en.wikipedia.org/wiki/Object_slicing
Object slicing happens at run-time not compile time. Your compiler error is caused by something else.

For more information on cloning, read this link. It includes a full example of cloning that should help.

edit: if you meant your original problem and why your copy constructors weren't working then I agree with your statement that your problem was probably a result of slicing.

C++: A Dialog | C++0x Features: Part1 (lambdas, auto, static_assert) , Part 2 (rvalue references) , Part 3 (decltype) | Write Games | Fix Your Timestep!

Quote:Original post by Slyfox
it again complains that it cannot convert parameter 1 from *Model to AnimatedPlaneModel*.


This has nothing to do with object slicing. It means that you have code somewhere where there is a Model* and you are assuming that it specifically points at an AnimatedPlaneModel (because you are trying to do something with it that's specific to AnimatedPlaneModel*'s - such as assigning it to an AnimatedPlaneModel* variable, for example), when it could actually be pointing at any kind of Model.

In other words, you have a problem assigning from a general pointer to a specific pointer. Object slicing occurs (and does not produce a compiler error!) when you assign from a specific object to a general object.
With the original problem I recieved no compile errors and the application ran fine I just noticed that I had lost my varying textures because that data had not been transferred.

This happened because my model pointer m_pModel was using polymorphism to point at a AnimatedPlaneModel and the additional data held by the AnimatedPlaneModel was lost when the pointer's data was copied back into another Model pointer. Is this still not slicing?

It was only when I was trying to implement the virtual clone function that I was recieving compile time errors. I am now trying again using the link submitted by nobodynews.

Cheers!

edit: btw the reason I said again was because in the first instance of experiencing the slicing I tried to use the AnimatedPlaneModel copy constructor but it rejected me passing the model pointer into it for obvious reasons.

[Edited by - Slyfox on April 23, 2010 6:52:30 AM]
Problem solved thanks to cloning! Thanks everyone for your help, for anyone following this thread I simply did the following....

Within my Model class header file I added:
virtual Model* Clone() const{return new Model(*this);};


Similarly in my AnimatedPlaneModel header file I added:
virtual AnimatedPlaneModel* Clone() const{return new AnimatedPlaneModel(*this);};


then all I had to do was in the copy constructor of animal I replaced the line
m_pModel = new Model(*rhs.m_pModel);//  With this linem_pModel = rhs.m_pModel->Clone();


Now everything has been copied correctly and no data has been lost, thanks again!

This topic is closed to new replies.

Advertisement