Archived

This topic is now archived and is closed to further replies.

Inheritence: Copying Up

This topic is 5533 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

Say I have two classes:
class CObject {...}
 
and
class CPlayer : public CObject {...}
 
Now, I need to create a copy constructor for CPlayer.
CPlayer::CPlayer(const CPlayer &p)
 
How do I ensure that all the data in CObject is copied along with the data in CPlayer? I''m thinking something like
CPlayer::CPlayer(const CPlayer &p) : CObject(p)
 
Will that even come close to working?

Share this post


Link to post
Share on other sites
Ok what you have done there is given yourself a shallow copy constructor (one that just copies the memory). A shallow copy constructor is provided automatically by C++ so there is no need to do this.

You only need to make your own copy constructor if you have some dynamic data. Then you need to do some extra work to copy the objects rather than the pointers.

A shallow copy constructor will just copy the pointers so you just get copies of those pointers but the same old object.

Share this post


Link to post
Share on other sites
Yeah, those were just examples, I left them empty for clarity. I know how to write a copy constructor
My problem is, the base class has an array (well, a std::map) that I need to copy when I pass the derived class around. More specifically, I have a std::vector of CPlayers. This requires CPlayer to have a copy constructor. I could manually copy each field in the CObject class in CPlayer''s copy constructor, but then I would have to do this for each derived class . As you can imagine, I really don''t want to do that.

Basically, what I want to know is, Can I somehow call a base class''s copy constructor from a derived class?

I don''t want to do this:

CPlayer::CPlayer(const CPlayer &p)
{
uiSomeDataInCObject = p.uiSomeDataInCObject;
fSomeDataInPlayer = p.SomeDataInPlayer;
}


Since it means that I would have to put "uiSomeDataInCObject = p.uiSomeDataInCObject;" in the copy constructor of each derived class.

I need a more general solution. Any ideas?

Share this post


Link to post
Share on other sites
Ok then well If you wrote a copy constructor for the CObject then your original idea of calling that constructor in the initalization list should work fine (provided you wrote the CObject copy constructor correctly).

Hope this helps

Share this post


Link to post
Share on other sites
quote:
Original post by ze_jackal
I''m thinking something like

CPlayer::CPlayer(const CPlayer &p) : CObject(p)


Why don''t you try it out by yourself first before posting here? I''m a little tired right now, but I think that

CPlayer::CPlayer(const CPlayer &p) : CObject(p){}

would compile fine and do as expected.

Cédric

Share this post


Link to post
Share on other sites
When a dervied class''es copy-ctor is invoked, the base-classes copy-ctor''s are also invoked - just like default construction.
You only need a copy-ctor if the class contains pointers, references, or handles.

If you want to make copies using CObject*''s, you need more than just copy ctors. You need to add a virtal method to CObject called Clone.


struct CObject
{
virtual CObject* Clone()=0 {return new CObject(*this);}
};

struct CPlayer : CObject
{
//This is called a co-variant return-type
//It still overrides CObject* CObject::Clone()=0
virtual CPlayer* Clone() {return new CPlayer(*this);}
};


Then, given COjbect*''s you can reliably copy them using the virtual Clone method, which invokes the correct copy-ctor. (Well-formed copy-ctor''s are required for all participating classes).


//When you call Clone from a CObject*, it returns a CObject*
CObject* obj = new CPlayer;
CObject* copy = obj->Clone();

//If you call Clone from a CPlayer*, it returns a CPlayer*
CPlayer* player = new CPlayer;
CPlayer* copy = player->Clone();

//That''s what the covariant return-type does for you

Share this post


Link to post
Share on other sites
Thanks for your help, but I think I may be asking the wrong question. My CObject class has a member Actor (of type CActor) which contains a std::map<>. CPlayer is derived from CObject. CActor has a copy constructor and operator= defined like so:

CActor::CActor(const CActor &act)
{
Motions = act.Motions; //Motions is a std::map<>
};

//this is a member function
CActor& operator=(const CActor &act)
{
Motions = act.Motions;
return(*this);
}


''Motions'' is the only variable in CActor. It holds Animations referenced to std::strings, so that I can switch animations by name (ie, std::map).

Now, I have a std::vector. I fill it like this:

//''Players'' is a std::vector
Players.push_back();
Players[0].SetWorldLocation(100 * 16, 142 * 16);
Players[0].SetDrawLocation(335, 269);
/*...*/


I realize its a bit of a hack (eventually I''ll read from a text file) but it does work. Almost. As soon as I try to add another player and call Players.push_back(), the Actor for Players[0] is trashed and the Motions map is empty. If I don''t call Players.push_back(), everything works fine. (Of course, I could just push_back a few before filling them, but that doesn''t seem like the best option...I want a more flexible solution.)
So, my question is, what copy semantics does a std::vector<> require a class to have? Copy construtor, operator=, or both? And how could I go about implmenting the copy functions? Magmai''s answer isn''t quite what I''m looking for, since I don''t want to deal with pointers if possible. The initialization list thing works in a simple little test project, but doesn''t seem to have fixed it on a larger scale (cedricl: now you know why I asked...) I''m thinking this has more to do with the std::vector than anything else.

Also, how can I create operator= from a copy constructor? I normally just cut&paste, but I need a better solution.

Share this post


Link to post
Share on other sites