Infinite Loops "The Blog"

9/4/06

C++- Pointers, references and CATS

This is a recent thread from August 2006 , you can access it here. 

First post is by Gimli, our resident Intern and on quest for not the ring but C++ knowledge.  Pim has
taken him under his wing and is doing his best to teach and explain things -- and remain calm.

I have taken parts of posts as they can be long.  If you want the full version please read it in the forum.
As always my words below are in purple.

Gimili:

OK, Pim, I'm still working on my work-in-progress, so if you get some time to see my ideas and let me know what you think, I will work on implementing it. I'm pretty sure I see what I was supposed to do, so I just need your input.

Alas, I need to move on. I'm pretty sure I've got enough of a grasp of pointers (at least as far as my book is concerned) so although I don't know everything about them, what I do know will get me through my CURRENT book, and I will learn some more stuff later on.  I think it works that way for most things anyway. Learn the basics somewhere, and expand on it later somewhere else.

Gimli is lulled into a false sense of security on pointers.  A good grasp is slowly loosing hold.

Pim:

OK, you know what the this pointer does, don't you? So I only need to explain about the overloaded operator?
Well, overloading means, in effect, redefining. What you do is take an existing operator, in this case, ++, and redefine it for this particular class, so that when you apply it to this class, this is what happens instead of the "default" behaviour.
You can't define new operators in this way. You can't say, oh, I'm going to take the \ or the $, and have it perform multiplication or whatever. You can only use the existing ones. And ++ is already there.
You do know about ++, right? You know the difference between C++ and ++C? OK.
So what you do here is rewrite ++ to increment an object of type Counter. That's it.
Questions?

Pim-- you sure you want questions??

Gimili:

Heh. Actually not really. That's my main problem, I think. Like I've seen the this pointer used in this way: int someVal { return this->itsVal } but that's kind of moot.  So when the program says return *this; is it referring to the result of ++itsVal ?

So maybe a bit of an explanation on the this pointer and its uses (and/or examples)...

This is pointing to that :)

Pim

Yes, all the items in a class can access all the other items in it. The distinction between private / protected / public is only made for other entities, outside of the class. (With a couple of exceptions of course, but we won't go into that.)

The this pointer is the address of the current object.
So if you have a class

class whatever{   public:   whatever* getthis() {return this;}};
and you have an object of class whatever

whatever what;
then what.getthis() returns the same as &what. That's all there is to it. There are no other tricks involved. It's simply that inside the class, you can't use &what, because you don't have what.

Groetjes, Pim

&WTF ?

Bunch of posts with code referring to a class called CAT with members frisky and boots follows.Gimili is still confused-- this is now in the area of Copy Constructors.

Gimli:

The book says this: A new CAT, boots, is created, using the copy constructor and passing it in frisky.

I still don't understand... does that mean that boots now has all of frisky's data? And how can an object take a parameter like that?

I however want to know who is feeding the cats?  * food

Pim
Yes. That's what the copy constructor does: it copies an object, so it needs to know which object to copy.
You must remember that references are not references to types (classes), they're references to objects; real, existing objects.

" Then, when the copy constructor is defined, the CAT object (???) rhs is created, "
No, it's not created. The object is already there, it's just referred to as rhs.


" and public accessor methods are used. "
Yes. Well, they don't need to be public, actually.


" But if there is a constructor that already makes data available on the free store, why use 'new' in the copy constructor as well? "
Because the copy constructor is a constructor!
The other constructor is not used when copying an object in this way, only the copy constructor is. See, when you're creating an object, only 1 constructor is used.
If you were to have a third constuctor, with yet different parameters (the age for instance), you'd need to use new in that constructor as well.


" And how can an object take a parameter like that? "
Sorry? It's not the object that takes a parameter, it's its constructor that does.
A constructor works the same way as a function does.

Stormblade now enters in -- maybe he has the catfood.

Stormblade:
From your question I think you may not have references down quite perfectly. At least not in their entirety. Remember that references are aliases to objects. You can not create a reference that refers to nothing. That is their main difference from pointers. A pointer can be set to point to nothing at all. It's a variable in and of itself and has it's own identity.

A reference doesn't have it's own identity. It exists only as an alias to an object. In order to create a reference for an object, that object has to already exist. The reference and the object it refers to are one. They only differ in the names. It's just another way to refer to an object that already exists somewhere.

Codebabe still understands this explanation.

Gimli

OOooohhhh... I getcha.

So CAT& in the copy constructor part of the class declaration is saying that there's a reference of a CAT, and later, rhs is the name given to it, which is a reference to a CAT, which has all the attributes of a CAT? so rhs.GetAge() is returning the age that's in CAT (in this case, since frisky is passed as a parameter at CAT boots(frisky), boots (and thus rhs inherits all the data from frisky).

I think I get what you're saying

A quiet hush, does Gimli really get it ? The below is not the post right after above.

Gimli:

"rhs contains a copy of all of frisky's member variables."

Pim

No, no!
It's a reference! A reference! Not a copy!
Pfff, how do I explain this?

Ehm,

Storm! Help!

Stormblade:

Think of it this way. This hopefully won't confuse you further but ok. You declare your copy contructor. It is invoked when a copy of the object is needed. Here's how you can visualize it.

I come into your office and tell you that I need you to make a copy of my resume. You don't have a copy machine so you have to do it yourself. I hand you my resume (This is like passing the object to your copy constructor) and then you get a piece of paper (LIke allocating memory or whatever you need) and you start copying. To copy my resume you need to be able to look at my resume to copy it.

That's in essence what the copy constructor does. Remember to think object like. The copy constructor allows you to create an object that knows how to copy itself. Inside the function what you are doing is copying FROM an object. So you have to have the object you are copying FROM sent to your function.

That's what that reference is. It's a reference to the object you need to copy from. You are the copy and you are getting your information from the original in order to make yourself the perfect copy of that object.

References are used many times because of their nature. You can't have a reference referring to nothing so the recommendation is to always use references instead of pointers unless you absolutely have to use a pointer and in those cases it's usually a result of poor planning or design or both.

My headache is getting worse at this point.  * Tylenol

Pim

No. Don't despair though, we're getting close.
It would change too, if you had made a shallow copy. However, because you have made a deep copy, utilising the copy constructor, boots' data (which are full copies of frisky's) are boots' and boots' alone!
If you understand Storm's explanation, there's no need to read on. But if not, maybe a different analogue helps a little.

Think of an object that contains data as a man holding a suitcase. The object is the man, the data is the suitcase.

If you make an exact copy of the man, you will have a second man, which is identical to the first, and he is holding the VERY SAME suitcase.
So now both men are holding this suitcase.
Then if the first man would change something in the contents of the suitcase, the second man will find his suitcase changed too. Because it's the same suitcase!

So in most cases, what you want to do is make a copy of the man AND his suitcase. That means you can't just duplicate the man, you've got to duplicate the suitcase as well. Only then will each man have their own suitcase.

Does that clarify things a bit? If it only muddles things, I'll have to think of a clearer analogon.

Umm-- are the cats in the suitcases? Man I hope they can breathe.

Gimli:

It makes sense, but could you, using the man/suitcase example, state how it relates to the frisky thing, just so it has a bit more connection? I may have to re-read what Stormblade posted a while ago about deep and shallow copies to see how they differ, and how a deep copy was made from the code we used, rather than a shallow copy.

Pim:

A bit more connection? OK, OK, have it your way.
<mumbles>A cat holding a suitcase... Pfff, what will they think of next?</mumbles>

No, seriously now. In order to make the difference clear between deep and shallow copies, I want to make the CAT class a little bigger, so that it doesn't contain only pointers, it contains actual data as well.
class CAT {   CAT();           // default constructor   CAT(CAT& rhs);   // copy constructor   int itsEyeColor; // its eye color  <-  this is the new one   int* itsAge;     // pointer to its age   int* itsWeight;  // pointer to its weight};
Of course, there's also the functions that retrieve the values, but we're not concerned with those now.
Suppose you create a new CAT.

CAT Frisky;

What you do here is call the default constructor, which gives the CAT a certain eye color, and also, to follow the analogon, creates two documents in its suitcase, one documenting the age and one documenting the weight.

OK so far?
Well then, there are two ways in which you can make a copy of Frisky: shallow copy or deep copy.

Shallow copy
If there is no copy constructor, you can still make a copy of Frisky.

CAT Boots(Frisky);

The compiler doesn't mind. It will just make an exact copy of Frisky. Only of Frisky, mind you, not of its suitcase. Why would the compiler make a copy of a suitcase if you ask it to make a copy of a CAT?
So what you have here is Boots, an exact duplicate of Frisky. Since Frisky is holding a suitcase, Boots will also be holding that suitcase.

OK so far?
Now if you can visualise that, you will realise that you can change Boots' eye color without affecting Frisky's. You copied the eyes, remember? So Boots has eyes of its own, and you can alter them whatever you want.
However, what you can not do is change Boots' age without affecting Frisky's. You didn't copy the suitcase, so it's still Frisky's suitcase that Boots is holding. If Boots opens the case and changes the age on the document, Frisky's age will change with it!

OK so far?
(You do understand that I expect a series of "yes"es in your reply to this message, do that I will know you have read each of the "OK so far" questions?)


Deep copy 
If you don't want to happen what happens above, you will have to write your own copying routine rather than let the computer handle it.
Your own copying routine will copy not just the CAT, but also the suitcase. What the copying routine - the copy constructor - looks like, is detailed in an earlier message, and I won't go into that again.
Well, from there on it's simple. After

CAT Boots(Frisky);

you will have two CATs and two suitcases. So Boots can open its suitcase and alter the documents inside it, but Frisky's will remain unaltered.

OK so far?


Groetjes, Pim

Progress has been made.  or has it?

Gimli:

Yes! OOOooooh YES! YEEEEESSS!!! Oooooohhhh....

Ahem.... erhm... now where were we....

" <mumbles>A cat holding a suitcase... Pfff, what will they think of next?</mumbles> "

I laughed out loud at that one. Haha.

So having the pointers, pointing to a place in memory, makes it so that if you change the variable that's being pointed to, then it changes them both, unless you assign each one a separate place in memory, using new, like they have done in the example?

But without a pointer (such as the itsEyeColour, a CAT Boots can have his own eye colour because that CAT has, although a copy initially, has the ability to change those variables.

Is this what you're saying?  I hope so, because I was pretty impressed with how you explained it. Made sense (I think, although I've said that before and look where I am)

Pim:

Yes. If you have Frisky with its pointer to its age, and you make a (shallow) copy, you also copy the pointer, so the pointer in the new CAT will point to the same memory location as the one in the old one, being as it is an exact duplicate.


As you can see, they also have the same eye colour, but you can change that in one cat without changing it in the other.

Groetjes, Pim

We are all amazed at Pims hidden talents as an artist.  We had no clue of his side of him. We will no doubt loose him when he is discovered in some French Cafe with his sketch pad instead of his laptop.

Gimli:

*laughing* Oh man, colour me impressed with your drawings. :P Totally crack me up.

Hey, while we're at it, do you have multiple user-names? Like NIPP2 perhaps? Because I was just surfing a promo, and I saw Pim (although I've seen him/you all over the place, just with a different name in the ( ). ) And this particular Pim, who had NIPP2 as the login name, also had, at the end of his post, "Groetjes, Pim."

I think I get what you've been telling me though. I really think I do. It's just a matter of a) actually knowing it, not just saying it (this we'll find out later I guess, since I seem to get things, and then I ask a question and apparently don't get it, like I had thought) and b) retaining the information I read, something I've always had trouble with to begin with (i.e. it takes repetition, perhaps more than usual, to grasp a concept.)

:)

EDIT: Oh yeah, when you think I should move on, let me know, and I'll keep truckin' with more questions.

Pim

If you find you need repetition, does it help to re-read the thread? This one for instance; I believe it holds lots of useful concepts, some of which you may not have grasped the first time, but you may understand it better when you read it for the second time.


Groetjes, Pim

Or third , fourth etc,

Well we think Gimili gets pointers now,  if not well he certainly has a couple of cute pets now.

 

 

 
About Infinite Loops
Sample of Resource Material from our Members in the Forum. Programming Information.
Blog Entries
Archive>
Calendar
«April 2024»
SMTWTFS
31123456
78910111213
14151617181920
21222324252627
2829301234

©2024 Delphi Forums LLC All Rights Reserved