Hello, everyone. Welcome back.
I hope you had fun with this challenge.
It can be a very tough challenge sometimes.
You've really got to understand what's going on with returning
references, returning values, const correctness and so forth.
So let's go through the solution.
I'm in the section 14 workspace in the challenge-solution1 project.
And here's one possible solution to this challenge.
There's obviously a lot of different ways to achieve the same result.
First thing is I'm in the mystring.h file.
And you can see here the prototypes for the operator member methods.
Remember, now this is the version where we're implementing all of
these operators as member methods.
So right away, we've got a little bit of an advantage in the sense that
since we're member methods we have access to all the private information.
So here we go.
We've got our unary minus that makes the string lowercase.
We've got our concatenation operator.
And remember, because we've got member methods here, this
will expect nothing, right.
There's nothing in the parameter list for a unary operator because
this object is the operand.
In the case of a binary, operator there's only one item to the right
in the parameter list, not two.
With non-member functions, it's different we'll have two.
Here is my equality operator, my not equal operator.
You can see they return Booleans, less than, greater than.
If you chose to do less than or equal to greater than
or equal to, that's great.
And then I've got my plus equal operator that expects a
right-hand side string obviously.
And then the left-hand side, we're assigning back to.
That's my concatenate and a sign.
There's my star or repeat operator in this case where I want to
repeat a string n number of times.
There's the star equal operator.
And then we've got our pre-increment and post-increment operators that
will simply make a string uppercase.
Notice the pre-increment returns a reference, the post increment
returns mystring by value.
Okay, so there you go.
And let's go and see the implementations for these,
and they should be really straightforward, it's pretty much
what you've been used to doing.
So let me start right here at the very beginning.
Right here on line 94, we're looking at equality.
So let's take advantage of that string compare function, right.
So we're going to compare this string with the
right-hand side object string.
And if they're equal to 0, then they're the same the
Not equals is exactly the same except I'm just putting a bang
in here, I'm just saying -- I'm negating that result.
We could certainly call this guy.
But it's simple enough just to negate what we get back here.
The less than is the same idea.
I'm using std string hump again.
And I'm checking to see if the value return was less than 0,
and I'm returning that result.
Greater than exactly the same way.
So you can see how trivial these methods are to implement because
the std string comp function is really doing all the work for us.
Now the make lowercase we saw this in the slides.
And we saw this in some of the code examples that we did as well.
What we need to do here is allocate a character buffer right here an
array of characters on the heap that's the length of the string
that we're in question plus one.
Then we need to copy the string over to buff and then just
loop through that buffer area.
And basically, make all those characters lowercase, right.
And we're using the std to lower function right here to simply make the
lowercase version of that character.
I'm creating the temporary object, which I'm returning and
don't forget to delete the buffer as we mentioned in the slides.
Otherwise, we'll leak that memory and that's not something we want to do.
The concatenate method is very, very similar.
We're creating an area in on the heap.
This time it has to be big enough for both strings plus 1.
So we're taking the length of str and then the like the length of right-hand
side str and adding 1 to them.
I'm copying the string to the buffer, and then I'm concatenating
the other string the right-hand side string to that, creating a
temporary object and returning it and deleting my area again.
Very, very common pattern that you can see.
Now let's talk about plus equal since we've already overloaded
the concatenation operator.
Let's take advantage of that.
So you can see this basically becomes really one line of code,
the return doesn't even count because we've got a return.
So what we're saying here is that the current object is equal
to the current object plus the right-hand side object, right.
So this right here we'll call this operator that we've already overloaded
and take care of everything for us.
So this becomes a very trivial method once we've overloaded
the concatenation operator.
Here is the repeat.
And what I can do here is I can take advantage because remember
multiplication or repeating is just a bunch of additions.
So what we can do here is we can take advantage of that.
So we can create a temp object to just an empty temp object and
then just loop end times and add this to the temp object, right,
which is exactly what we expect.
We're incrementing this so many times.
And then we just return the temp object, in this case.
We could do it all in code.
If we do it like that if you like, one is going to be a little bit
more efficient than the other.
But this works really well and this is very, very readable
and modifiable code, which is my preference right here.
Here's the repeat and assign, same idea as the plus equal.
This is the star equal.
So this equals this times n.
We're going to call the overloaded star operator, a repeat operator in
this case to do it all for us, so this method becomes trivial again.
Okay, and now let's take a look at the last couple of methods here the
pre-increment and the post-increment.
They both make the string case.
The difference is in the semantics.
So let's take a look at this one right here, pre-increment.
This one is dead simple.
We've got an object.
It's got an str, pointer that points to a character array on
the heap to do is loop through that character array and make
everything in there two upper.
That's it. And then we return the current object.
There's no need to copy anything, move anything over.
It's the same string we're pointing to, we're just
simply making it uppercase.
And in the case of the post increment, remember, the post
increment is using that int right there, which is just a placeholder.
It's unnamed.
We don't even use it in here.
It's only used by the compiler behind the scenes.
This returns an object by value.
So what we're doing is we're making a temporary copy of the current object.
That's what this is doing right here.
Then we're calling the pre-increment function, this guy right here.
That's going to increment that string, make it uppercase in this case.
And then we return the temporary object that we
saved, that was the old value.
So these are the semantics for post increment, it's going to
be a little bit different than the pre because I've got to
return the old value, right.
That makes sense because what we're assigning is the value then
we're incrementing the string.
So there you go.
That's a real simple implementation for all of these operators.
It may have taken you a while.
That's okay, that's part of the learning process.
I remember when I first did operator overloading, it's hard to wrap your
head around whether you're returning references or values and you know
what what exactly is going on here.
The last thing we'll do is let's take a look at main and
you'll see some test cases here.
And what I'd like to do I'll just run this real quick.
And right there's our output.
And then it says enter a string to repeat.
So let me just enter a string that looks like dash 00 dash
I'll put three 0, just something that we can really see.
And this is testing the extraction operator as well.
And how many times would you like to repeat it.
Let's say I want to repeat it five times.
And there we go.
And I'll get back to this output in just a second, but let's go back to
our main here and walk through this.
You can see right here that I've got mystring a which is frank,
mystring b which is frank.
And I'm saying is a equal to b.
And this will print out true or false because I've set this
modifier right here on the stream.
So a obviously is equal to b, so we expect a true.
That's what we have right here.
Is a not equal to b?
Well, that's false so we get the false.
Then we set b to George, and we use some of the other comparison operators
in addition to the ones we just did.
So in this case, frank is definitely not equal to george, right.
So we expect this to be false, which it is right here.
Is frank not equal to george?
That's true.
Is frank less than george.
That's true.
And finally, is frank greater than george?
That's false.
So you can see that output right over here.
Okay now we'll get to some other ones.
In this case, I've got s1 is frank all uppercase, and I'm using the
unary minus right here to make it all lowercase and then I'm outputting S1.
And so you can see we expect lowercase frank and that's
what we have right here.
The next is using the concatenation operator.
So remember, s1 is lowercase frank.
And we're just saying tack on five asterisks to that, concatenate
five asterisks to the end of that.
So we expect this to be frank, followed by five asterisks and
you see the output right there.
And then we're doing it again except this time we're using plus equals.
So I'm saying s1 plus equals.
I think five dashes again.
In this case dash is not stars.
So what we expect is s1 which is right here frank five asterisks, and
we want to append those dashes to it.
So the output is something like this is what you see right here.
Okay, now we're going to use the repeat operator right here.
We're simply saying s2 is one two three four five and give me three
copies of that and assign it to s1.
So what we expect is 1 2 3 4 5, 1 2 3 4 5
and 1 2 3 4 5, just what we see right here.
Okay, let me scroll this up just a little bit so we put
all this on the same screen.
So we're right about -- okay.
So that's better.
So now I've got s3 is abcdef.
And all I'm saying is give me five copies in this case of s3
and just put it right back in s3.
So we expect five copies of abcdef.
That's what we're getting here.
You can see the five copies of that string.
Now we're using the insertion and extraction operators
we're testing those.
So we've got a couple of variables here repeat string and repeat times.
And we're just simply asking the user interest string to repeat, and we're
using the extraction operator to read that right into repeat string.
That's our own overloaded extraction operator.
So I typed in dash three zeros and a dash.
And then how many times would you like me to repeat this.
I entered five times.
And I simply wrote repeat string star equals repeat time.
So give me five copies of that.
And then I'm displaying it right here 1 2 3 4 5 copies of that.
Then the next line just gives me 12 copies of what I just did.
So that's going to give me 5 times 12, it's going to give me 60 of
these guys printed out here, which is just a really simple test.
And then finally, the last tests for the concatenation operator
are right here I've got repeat string is just repeat me.
Then I'm simply outputting repeat string plus repeat
string plus repeat string.
So I expect the three copies of that to display and there they are: repeat
me, repeat me and repeat me again.
Okay, there were chaining the concatenation operators.
And notice that here we're creating actually a temporary unnamed.
So you can uncomment the move assignments and the move
constructors and you can see how that's happening efficiently.
Here we're saying repeat stream plus equals, repeat
string plus times three.
So we're basically adding this time right.
So we're taking this repeat string, which is repeat me.
Give me three copies of it and then adding it right back to repeat me
which had one copy in there already.
So we expect to end up with four copies.
We have 1 2 3 and 4 right here.
And then the last several test cases are the posts and pre-increments.
So we'll do the pre-increment first.
In this case, I've got frank.
Let me scroll that down just a little bit right there.
So in this case, I've got a pre-increment.
Mystring is frank with an uppercase f.
And I'm saying pre-increment s.
So I expect frank to be uppercase when I output it and
that's what I'm getting here.
I'm setting s back down to lowercase and outputting it right there.
I'm saying mystring result pre-increment s.
So when that happens, I expect both s and result to contain
the uppercase frank which is exactly what's happening here.
And then finally, we'll test the post increment where we're setting s to
frank and just simply incrementing s, we should get remember post
and pre-increment all alone in the statement mean the same thing.
So in this case, I've got frank as uppercase, which I'm displaying.
I'm making frank lowercase, and then I'm testing the post increment
in this context here, which means assign the lowercase version
to result and then increment s.
So result we expect to be lowercase, s we expect to be
uppercase, and there you go.
Okay, so a lot of talk with the test cases, but they're
important that you understand what they're supposed to do.
When we look at the challenge solution 2, we won't go over these
again since we went over them here.
But that's pretty much it.
Implementing these as member methods is pretty straightforward.
It's just a matter of understanding.
When we're changing str, we've got the right-hand object as well.
Do we return a reference; do we return by value?
And that's it.
If you have questions, please let me know.