Sign in to follow this  
AcidZombie24

when to overload copy ctor?

Recommended Posts

When should i overload the copy ctor? My recent problem had to do with the compiler initializing the class the wrong way when i assign classes to another class. I had to overload the ctor and it fixed itself. Right now the root class has a copy ctor. I thought i only need to create a copy ctor for class directly using it. Right now it seems like i need to write one for every part of the chain. What are good rules to follow for copy ctors? does anyone know of a good article on this?

Share this post


Link to post
Share on other sites
Quote:
Original post by AcidZombie24
When should i overload the copy ctor?

When the default copy constructor isn't good enough - it does a member by member copy. So if you have members pointing to memory belonging to the object, you need to implement the copy constructor, assignment operator and destructor yourself (because copying just the pointer is not what you want - you also want to copy the pointed-to memory).

Share this post


Link to post
Share on other sites
When you write a class, it can be a good idea to assume it could be used anywhere...

It might get copied, so make sure it follows the rule of three, or prevent the object being copied by making the copy constructor and assignment operator private and unimplemented. (In fact when I code review code at work, failure to follow the rule of three, or prevent copying, I note as a bug)
Methods might get called on a temporary object, so make sure that methods which should be const are marked const. (I usually note failure to do that as a bug as well)
If someone might find it apropriate to put the object in a set, consider giving it a less-than operator.
Consider providing an operator == in case someone wants to use std::find to find an instance of your class.
Provide a no-throw specialisation of std::swap if it can be swapped faster then the naieve way. (Speeds up std::sort of a vector of your objects)
Is your class going to be used in code where exceptions might get thrown? Have you thought about what level of exception guarantees your class provides? Do you have internal members that themselves might throw exceptions?

There could be others, but suffice to say it's nice to use a class where the coder has thought of everthing.

Share this post


Link to post
Share on other sites
There's something else you have to watch out for. This mutton-headed thing I did bit me for weeks in a side project. The bit I read in the first post about 'assigning a class to another class' triggered this thought, so I think it is related but if not then... oh well :)

Let's say you have base class B and derived class D. If you create an instance of B on the heap and later cast it to D, things seem ok. Polymorphism at it's finest. My derived class added some new member variables, but they weren't getting initialized at the point of casting. So I wrote a copy constructor hoping to solve the problem, and it worked until I then wanted to delete the allocated object. What ended up happening is that the delete operation tried to remove the size of derived class D from allocated memory, which was bigger than its allocated size, the size of B, so I got an access error from the program when it tried to delete.

Moral of the story: rule of three is a great rule but still won't solve all your problems if you aren't careful about what you're doing to begin with!

Share this post


Link to post
Share on other sites
Quote:
Original post by MajorShredd
There's something else you have to watch out for. This mutton-headed thing I did bit me for weeks in a side project. The bit I read in the first post about 'assigning a class to another class' triggered this thought, so I think it is related but if not then... oh well :)

Let's say you have base class B and derived class D. If you create an instance of B on the heap and later cast it to D, things seem ok. Polymorphism at it's finest. My derived class added some new member variables, but they weren't getting initialized at the point of casting. So I wrote a copy constructor hoping to solve the problem, and it worked until I then wanted to delete the allocated object. What ended up happening is that the delete operation tried to remove the size of derived class D from allocated memory, which was bigger than its allocated size, the size of B, so I got an access error from the program when it tried to delete.

Moral of the story: rule of three is a great rule but still won't solve all your problems if you aren't careful about what you're doing to begin with!
I assume by that last statement you meant that you should never have casted B to D? The language tries to stop you from doing something stupid like that. A dynamic_cast would give NULL and a static_cast wouldn't compile. You would have had to force the issue with a reinterpret cast.
Having intentionally done the wrong thing with the cast I presume you then later tried to delete ity through a pointer to the derived type of which the instance is of course not an instance of. The only problem with that relates back to the fact that it was wrong to perform the original cast.
The only point I think you've made is that doing stupid things is, well ... stupid.

Share this post


Link to post
Share on other sites
Quote:
Original post by iMalc
Quote:
Original post by MajorShredd
There's something else you have to watch out for. This mutton-headed thing I did bit me for weeks in a side project. The bit I read in the first post about 'assigning a class to another class' triggered this thought, so I think it is related but if not then... oh well :)

Let's say you have base class B and derived class D. If you create an instance of B on the heap and later cast it to D, things seem ok. Polymorphism at it's finest. My derived class added some new member variables, but they weren't getting initialized at the point of casting. So I wrote a copy constructor hoping to solve the problem, and it worked until I then wanted to delete the allocated object. What ended up happening is that the delete operation tried to remove the size of derived class D from allocated memory, which was bigger than its allocated size, the size of B, so I got an access error from the program when it tried to delete.

Moral of the story: rule of three is a great rule but still won't solve all your problems if you aren't careful about what you're doing to begin with!
I assume by that last statement you meant that you should never have casted B to D? The language tries to stop you from doing something stupid like that. A dynamic_cast would give NULL and a static_cast wouldn't compile. You would have had to force the issue with a reinterpret cast.
Having intentionally done the wrong thing with the cast I presume you then later tried to delete ity through a pointer to the derived type of which the instance is of course not an instance of. The only problem with that relates back to the fact that it was wrong to perform the original cast.
The only point I think you've made is that doing stupid things is, well ... stupid.


Yes, that was exactly my point, noted in the very last sentence of the post - be careful not to do stupid things. However I was not thorough in explaining that there was no reason to cast in the first place. I should just have used D from the start, and that's what I ended up doing in that program.

Share this post


Link to post
Share on other sites
Assuming your 'overloaded copy constructors' are ones taking a single argument of a different type to the class then they will implicitly perform type conversions. The compiler however won't combine more than one of these type conversions to convert between very different types.

To avoid unwanted type conversions I'd recommend declaring all single argument constructors explicit unless there's a very good reason not to. You can still do the type conversion by calling the appropriate constructor directly if need be.

Here's a couple of articles I found that help explain that in more detail:

http://weblogs.asp.net/kennykerr/archive/2004/08/31/Explicit-Constructors.aspx

http://www.sjbrown.co.uk/2004/05/01/always-use-explicit/

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this