need some more help with copy constructors, this pointer, and polymorphism

Started by
2 comments, last by Zahlman 18 years, 4 months ago
I read about.com's c++ tutorial and understand how most of the language works; However, I'm having some trouble with a few aspects of the language. I understand when the copy constructor is called and what it does, but I don't see the difference between the copy constructor and the constructor. Both of them have the are just the same name as the class. Is it just that the copy constructor always takes a const reference to another instance? I understand that the this pointer points to the instance you are working with but I don't understand how something like this works. Say you have a point class and you have accessor methods to set the x and the y that look like this: point& set_x(int x){_x = x; return (*this);}. I don't really see how that works, its returning the entire instance is it not? So then how does that give you the x that you just set? I understand how polymorphism works, but I'm still a little confuesd by it. The page I'm quoting from is: http://cplus.about.com/od/beginnerctutorial/l/aa120602c.htm this is the function: void chorus(Pet pet, Pet *petPtr, Pet &petRef) { pet.speak(); petPtr->speak(); petRef.speak(); } "Next, a Rat object is created and its address is stored in a Pet (base class) pointer. This Rat object is then passed into the chorus function. The first parameter in the function's parameter list, pet, is a Pet object. We are passing in a "Rat" object as the first argument. You may recall that when you pass an argument by value, a copy is made. In this case, the compiler makes space for a Pet object and then copies the Rat object argument into it. Since the Rat object is larger, it doesn't fit. This is called slicing. Only the Pet part of Rat gets copied. When speak is called, it is Pet's speak method that is executed. Let's look at the second parameter, petPtr. This is a pointer to type Pet. When passed a pointer of type Pet holding the address of a Rat object, we get Rat behavior - "rat noise" is printed. This is polymorphism." I think the reason I don't understand this could be because I don't completely understand the copy constructor. I don't see how if its copying the rat instance it doens't have enough room to copy it and only copies the pet part of it. The pointer on the page is pointing to a Rat, so if a rat is being copied I don't see how only the base of it got coppied. I understand that the petPtr->speak(); would execute the rats speak function.
Advertisement
Quote:
Is it just that the copy constructor always takes a const reference to another instance?


Pretty much.

Quote:
I don't really see how that works, its returning the entire instance is it not? So then how does that give you the x that you just set?


Correct. It doesn't return the x. It returns everything. That's not an accessor, it's a mutator. Returning this allows you to chain the mutators together like this:

point().x(42).y(16);


Which default constructs a point and sets x and then y. Without the return you'd have to make that 3 lines.

An accessor does something like this:
int     get_x(){return(x);}


which copies x to the return, allowing you to use its value for stuff.

Quote:
The pointer on the page is pointing to a Rat, so if a rat is being copied I don't see how only the base of it got coppied.


Remember, it's for the first parameter, so pointers aren't involved. The compiler tries to copy the Rat into the first parameter [a Pet]. Remember that Rat inherits from Pet, so it is also a Pet. When the Rat is passed to the first parameter, the Pet parameter uses the Pet copy constructor (since it's being passed a Pet), and copies the Pet parts. The Rat parts are discarded.
eeek. i was just making two dumb mistakes. i saw that set_x was returning something and automatically thought it should have been the x. and I wasn't thinking that it was looking for a Pet and you were giving it a Rat. I just thought it was going to except a Rat. thank you so much for your help. I think I understand it all now.
Quote:Original post by yahn
I understand when the copy constructor is called and what it does, but I don't see the difference between the copy constructor and the constructor. Both of them have the are just the same name as the class. Is it just that the copy constructor always takes a const reference to another instance?


As per the usual rules of the English language, a copy constructor is a specific kind of constructor - one which copies. A constructor can basically take any set of arguments that any other function could (except that it also implicitly has a this-pointer to the instance memory that's about to get initialized. Oh, and don't try to write a copy constructor which takes the other instance by value; that's bad mojo. In general, you should pass class/struct instances by reference, qualifying them as const where appropriate.)

Quote:I understand that the this pointer points to the instance you are working with but I don't understand how something like this works. Say you have a point class and you have accessor methods to set the x and the y that look like this: point& set_x(int x){_x = x; return (*this);}. I don't really see how that works, its returning the entire instance is it not? So then how does that give you the x that you just set?


It sets that member, and then returns the current instance, by reference. Since it's not a copy (which you would get by returning by value), that then allows you to do what is called "operator chaining" - that is, if you write "myInstance.set_x(42)", then the result after that is myInstance - not a copy. So you can write for example "myInstance.set_x(42).set_y(23)", and both members are set.

Quote:I understand how polymorphism works, but I'm still a little confuesd by it.
...
I think the reason I don't understand this could be because I don't completely understand the copy constructor. I don't see how if its copying the rat instance it doens't have enough room to copy it and only copies the pet part of it. The pointer on the page is pointing to a Rat, so if a rat is being copied I don't see how only the base of it got coppied. I understand that the petPtr->speak(); would execute the rats speak function.


In C++, variables have types; values by default do not. When you pass a Rat by value to a function that expects "Pet by value", only enough space *is allocated* on the stack for a Pet instance, because the called function wants a base Pet instance and doesn't care about the other stuff. It is as though the function started out with an uninitialized Pet instance of its own, and you tried to copy the Rat into it. (With pointers or references, no such problem occurs. References explicitly request the polymorphic behaviour - "I want to use that object over there, warts and all", and pointers are all the same size regardless of what's pointed to.)

You might also want to read this.

This topic is closed to new replies.

Advertisement