1 00:00:05,430 --> 00:00:08,780 In the previous video, we saw how we can overload operators 2 00:00:08,780 --> 00:00:10,400 using class member methods. 3 00:00:11,190 --> 00:00:13,509 In this video, we'll learn how to overload operators using 4 00:00:13,520 --> 00:00:15,469 non-member or global functions. 5 00:00:16,570 --> 00:00:19,700 Since these are not member functions, we no longer have a 6 00:00:19,710 --> 00:00:22,709 this pointer referring to the object on the left-hand side. 7 00:00:23,110 --> 00:00:26,840 So since we very often need access to private attributes in the objects, 8 00:00:27,230 --> 00:00:30,440 you see these non-member functions declared as friend functions of 9 00:00:30,440 --> 00:00:32,799 the class in many applications. 10 00:00:33,630 --> 00:00:36,909 This isn't absolutely necessary since we can still use getter 11 00:00:36,920 --> 00:00:38,850 methods to access attribute values. 12 00:00:39,220 --> 00:00:41,839 But as I said, you often see them implemented as friends. 13 00:00:42,660 --> 00:00:45,429 I'm going to declare these overloaded operator methods as friends 14 00:00:45,429 --> 00:00:46,540 when we head over to the ide. 15 00:00:47,500 --> 00:00:50,679 So in the case of unary operators, a single object 16 00:00:50,679 --> 00:00:51,920 is in the parameter list. 17 00:00:52,199 --> 00:00:56,040 And in the case of a binary operator, two objects are in the parameter list. 18 00:00:57,790 --> 00:01:01,680 So let's overload the unary minus operator to make a string lowercase 19 00:01:01,680 --> 00:01:03,160 as we did in the previous video. 20 00:01:03,760 --> 00:01:06,599 We want to provide the same functionality we did before, 21 00:01:06,960 --> 00:01:10,020 and our use of the unary minus operator would look the same. 22 00:01:10,520 --> 00:01:13,250 Let's see how we can do this using a non-member function. 23 00:01:15,250 --> 00:01:18,180 In this slide, I'm assuming that this function has been declared 24 00:01:18,180 --> 00:01:21,770 as a friend to the mystring class since I'm directly accessing 25 00:01:21,770 --> 00:01:23,450 the private attribute str. 26 00:01:24,210 --> 00:01:26,670 Notice first that this is not a member function, 27 00:01:27,270 --> 00:01:29,790 it's a regular c++ global function. 28 00:01:30,260 --> 00:01:33,860 The function returns a mystring object by value, and it's 29 00:01:33,860 --> 00:01:37,570 named operator minus, and it expects a single parameter. 30 00:01:37,720 --> 00:01:41,020 In this case, obj is a mystring object reference. 31 00:01:41,940 --> 00:01:44,970 Now the code is essentially the same as it was in the member version 32 00:01:45,210 --> 00:01:50,550 except that the string data is in obj.str rather than in this str. 33 00:01:51,510 --> 00:01:54,380 We allocate storage on the heap, copy the object's string 34 00:01:54,380 --> 00:01:57,770 data, loop through and make the copied string all lowercase. 35 00:01:58,150 --> 00:02:01,180 Then we create a new mystring object using the lowercase string 36 00:02:01,180 --> 00:02:04,799 as the initializer, de-allocate the temporary storage and 37 00:02:04,799 --> 00:02:06,620 return the newly created object. 38 00:02:07,140 --> 00:02:10,600 Of course, you can't have both the member and non-member versions 39 00:02:10,600 --> 00:02:13,700 of this overloaded operator at the same time or the compiler 40 00:02:13,700 --> 00:02:15,050 wouldn't know which one to use. 41 00:02:15,820 --> 00:02:17,310 You can only have one or the other. 42 00:02:19,660 --> 00:02:22,759 You probably already figured out that overloading binary operators 43 00:02:22,760 --> 00:02:26,820 as global functions is basically the same except that now we have two 44 00:02:26,870 --> 00:02:28,540 arguments required by the function. 45 00:02:29,200 --> 00:02:32,589 The first argument is the left-hand side object and the second is 46 00:02:32,590 --> 00:02:33,880 the right-hand side object. 47 00:02:34,400 --> 00:02:37,420 Here you can see some example prototypes for some operators. 48 00:02:38,009 --> 00:02:40,859 Notice that they all have two parameters in the parameter list. 49 00:02:41,180 --> 00:02:44,799 I've named the first LHS for left-hand side and the second 50 00:02:44,890 --> 00:02:46,519 RHS for right-hand side. 51 00:02:47,310 --> 00:02:49,940 Then at the bottom of the slide, you can see how these operators 52 00:02:49,940 --> 00:02:53,809 can be used and the functions that c++ will call when it uses them. 53 00:02:56,020 --> 00:02:58,660 Let's see how we can overload the equality operator as 54 00:02:58,660 --> 00:03:00,150 a non-member function. 55 00:03:00,770 --> 00:03:04,910 Again, I'm accessing a private attribute str in the mystring class. 56 00:03:05,020 --> 00:03:08,130 So I'm assuming this function is a friend of the mystring class. 57 00:03:09,020 --> 00:03:12,430 The code is almost the same as it was for the member version except 58 00:03:12,440 --> 00:03:15,760 that now I have an LHS object instead of the this pointer. 59 00:03:16,369 --> 00:03:19,940 So we compare the left-hand side string to the right-hand side string 60 00:03:19,950 --> 00:03:21,899 using string compare as we did before. 61 00:03:22,450 --> 00:03:23,480 It's as simple as that. 62 00:03:25,350 --> 00:03:29,409 Finally, let's overload the binary plus operator so that we can use it 63 00:03:29,410 --> 00:03:31,570 to concatenate two mystring objects. 64 00:03:32,830 --> 00:03:35,579 We create Larry Moe and Stooges as mystring objects, 65 00:03:35,579 --> 00:03:36,730 as we did previously. 66 00:03:37,150 --> 00:03:40,130 Now when we use the plus operator, notice the methods that the 67 00:03:40,130 --> 00:03:41,910 compiler is calling in the comments. 68 00:03:42,410 --> 00:03:45,790 Also notice that each is called with two arguments as we expect. 69 00:03:46,480 --> 00:03:50,200 Finally, remember that with the member version, the left-side argument had 70 00:03:50,200 --> 00:03:52,009 to be an object of the class type. 71 00:03:52,420 --> 00:03:54,810 With non-member functions, this isn't the case. 72 00:03:55,200 --> 00:03:58,440 Either one or both arguments can be of mystring type. 73 00:03:58,540 --> 00:04:01,420 However, if you have two string literals that won't work. 74 00:04:01,690 --> 00:04:05,070 C++ assumes primitive pointer and not objects. 75 00:04:05,530 --> 00:04:09,039 So let's implement concatenation as a non-member function in the next slide. 76 00:04:12,500 --> 00:04:15,780 Here you can see that the function operator plus returns 77 00:04:15,780 --> 00:04:17,640 a mystring object by value. 78 00:04:18,190 --> 00:04:22,409 It also expects two mystring objects left-hand side and right-hand side. 79 00:04:22,670 --> 00:04:24,970 Notice that they're both constant references since we 80 00:04:24,970 --> 00:04:25,960 don't want to modify them. 81 00:04:26,710 --> 00:04:29,570 The code now is exactly as it was for the member version 82 00:04:29,869 --> 00:04:33,719 except that whenever I need the left-hand side object I use LHS 83 00:04:33,730 --> 00:04:34,990 instead of the this pointer. 84 00:04:35,300 --> 00:04:36,050 That's it. 85 00:04:36,170 --> 00:04:39,770 Again, both the member and non-member versions achieve the desired result. 86 00:04:40,010 --> 00:04:41,919 But remember, you can only use one at a time. 87 00:04:42,660 --> 00:04:45,590 Let's head over to the ide and overload some binary operators 88 00:04:45,590 --> 00:04:46,869 as non-member functions. 89 00:04:48,529 --> 00:04:50,140 Okay, so we're back in the ide. 90 00:04:50,550 --> 00:04:53,940 I'm in the section 14 workspace, and the project is 91 00:04:53,940 --> 00:04:56,630 mystream-operator-functions. 92 00:04:57,200 --> 00:05:00,810 This is the project where we're going to implement those 93 00:05:00,870 --> 00:05:05,419 three overloaded operators: the equality operator, the unary minus 94 00:05:05,420 --> 00:05:08,950 operator, which makes the string lowercase and the plus operator, 95 00:05:08,950 --> 00:05:10,570 which concatenates two strings. 96 00:05:10,920 --> 00:05:13,380 And this time, we're going to implement them as non-member 97 00:05:13,380 --> 00:05:15,920 functions or global c++ functions. 98 00:05:16,349 --> 00:05:18,670 First thing we're going to do is we're going to make them friends. 99 00:05:18,670 --> 00:05:20,159 We don't have to make them friends. 100 00:05:20,490 --> 00:05:22,689 But it's going to be a lot easier to write the code because they don't have 101 00:05:22,690 --> 00:05:24,180 to call those getters all the time. 102 00:05:24,410 --> 00:05:26,530 So we can do that right in the class. 103 00:05:26,530 --> 00:05:28,860 Remember, the class has to grant friendship. 104 00:05:29,180 --> 00:05:32,060 So we'll write the function prototypes here, and we'll 105 00:05:32,060 --> 00:05:33,350 start them off with friend. 106 00:05:33,800 --> 00:05:34,749 And we'll do the first one. 107 00:05:34,760 --> 00:05:36,280 The first one is returns a Boolean. 108 00:05:36,670 --> 00:05:39,619 The operator is the equality operator. 109 00:05:40,080 --> 00:05:42,980 And remember now since this is not a member function, we 110 00:05:42,980 --> 00:05:44,970 need two parameters, right. 111 00:05:44,970 --> 00:05:46,400 This is a binary operator. 112 00:05:46,630 --> 00:05:52,409 So the first one will be const mystring ref LHS for left-hand 113 00:05:52,410 --> 00:06:00,990 side and const mystring ref right-hand side, right. 114 00:06:00,990 --> 00:06:02,690 So that's one function prototype. 115 00:06:02,750 --> 00:06:04,630 We'll do the next one for the unary minus. 116 00:06:04,630 --> 00:06:10,239 So again, friend -- this will return a mystring object by value the 117 00:06:10,250 --> 00:06:13,829 operator, we're overloading is the the minus operator, the unary minus. 118 00:06:14,179 --> 00:06:17,259 And it expects a single mystring ref. 119 00:06:18,750 --> 00:06:19,920 And we could call this obj. 120 00:06:20,020 --> 00:06:21,160 We can call this anything we like. 121 00:06:21,160 --> 00:06:24,460 I think I called it obj in the slide, so I'll call it obj here. 122 00:06:24,970 --> 00:06:28,010 And then we've got another operator that we want to overload. 123 00:06:28,020 --> 00:06:31,790 In this case, it returns a mystring object by value again, and this 124 00:06:31,790 --> 00:06:33,380 is the concatenation operator. 125 00:06:33,380 --> 00:06:37,219 So it's going to be the plus operator, and it's a binary operator. 126 00:06:37,220 --> 00:06:43,500 So we've got const mystring ref left-hand side and const 127 00:06:45,500 --> 00:06:48,430 mystring ref right-hand side. 128 00:06:50,480 --> 00:06:51,300 Okay, so there we go. 129 00:06:51,500 --> 00:06:54,250 It doesn't really matter where you put these friend declarations in, 130 00:06:54,820 --> 00:06:56,960 doesn't matter if you put them in the private area, the public area. 131 00:06:56,960 --> 00:06:57,810 It doesn't matter. 132 00:06:57,910 --> 00:06:58,760 So there we go. 133 00:06:58,870 --> 00:07:00,869 Unless I have any typos that looks pretty good. 134 00:07:01,160 --> 00:07:04,809 Now what we'll do is we'll go to the mystring cpp and implement those. 135 00:07:04,960 --> 00:07:06,220 We can really implement them anywhere. 136 00:07:06,220 --> 00:07:09,539 But since they really add to the interface of the class, it's 137 00:07:09,540 --> 00:07:13,750 common practice to implement them right in here in the .cpp file. 138 00:07:15,020 --> 00:07:16,930 I'm going to implement them here at the end. 139 00:07:17,120 --> 00:07:18,110 So let's do the first one. 140 00:07:18,110 --> 00:07:19,090 Let's do the equality. 141 00:07:20,450 --> 00:07:23,580 And again, this is a regular function, it's not a member function. 142 00:07:23,580 --> 00:07:29,610 So we're going to say bool operator, double equal sign for the equality. 143 00:07:30,180 --> 00:07:34,070 This is a binary operator, so it expects same prototype we did 144 00:07:34,070 --> 00:07:41,569 before, mystring ref left-hand side const mystring ref right-hand side. 145 00:07:44,160 --> 00:07:45,780 Okay, so now we'll write the code. 146 00:07:45,969 --> 00:07:47,190 We're going to return. 147 00:07:48,580 --> 00:07:51,310 We're going to call std string compare. 148 00:07:52,910 --> 00:07:56,110 And what are we comparing, we're comparing the left-hand sides string 149 00:07:56,630 --> 00:07:58,810 to the right-hand side's string. 150 00:07:59,429 --> 00:08:01,739 See the difference between this one and the member function. 151 00:08:01,750 --> 00:08:04,419 The member function, we really didn't have this guy here. 152 00:08:04,420 --> 00:08:05,739 That was the this pointer. 153 00:08:05,990 --> 00:08:08,480 So we did this str or simply str. 154 00:08:08,660 --> 00:08:11,190 But here we've got those two objects, so that's what we're going to do. 155 00:08:11,420 --> 00:08:14,409 So we're going to compare this to 0, and that's what we're going to return. 156 00:08:15,309 --> 00:08:16,570 And that should be done. 157 00:08:17,509 --> 00:08:17,779 Great. 158 00:08:17,800 --> 00:08:20,020 Now let's do the make lowercase. 159 00:08:23,170 --> 00:08:25,190 Notice again, this is not a member function. 160 00:08:25,190 --> 00:08:27,720 If it was a member function, it would look something like that, right. 161 00:08:27,920 --> 00:08:28,370 It's not. 162 00:08:28,370 --> 00:08:31,040 This is just a regular global function. 163 00:08:31,600 --> 00:08:33,000 So here's make lowercase. 164 00:08:33,349 --> 00:08:37,039 Make lowercase returns a mystring object by value. 165 00:08:37,590 --> 00:08:41,159 It's operator minus the unary operator we're overloading. 166 00:08:41,400 --> 00:08:44,110 And since it's unary, there's going to be one parameter 167 00:08:44,110 --> 00:08:45,250 in this parameter list. 168 00:08:45,620 --> 00:08:49,370 And it's going to be a mystring ref and we'll just call this obj. 169 00:08:49,370 --> 00:08:51,889 I think that's what I called it in the slides, and I'll stick to that name. 170 00:08:52,860 --> 00:08:53,710 That's it. 171 00:08:54,139 --> 00:08:55,770 Now let's write the code again. 172 00:08:55,770 --> 00:08:57,340 Again, it's the same code we had before. 173 00:08:57,340 --> 00:08:58,639 We need a buffer area. 174 00:08:59,480 --> 00:09:02,360 And what we're going to do is we're going to allocate a new array of 175 00:09:02,360 --> 00:09:03,910 characters in that buffer area. 176 00:09:04,440 --> 00:09:05,000 How big? 177 00:09:05,010 --> 00:09:09,480 Well, we're going to ask std strllen to give us the length of. 178 00:09:09,980 --> 00:09:12,550 Again, what is this now, it's obj.str. 179 00:09:14,670 --> 00:09:17,249 Right now we have access to that because we're a friend. 180 00:09:18,549 --> 00:09:20,930 And we're going to add the one for the string terminator. 181 00:09:21,400 --> 00:09:25,709 Now that we've allocated the space, we're going to string copy 182 00:09:26,590 --> 00:09:32,350 into the buffer from obj str. 183 00:09:32,929 --> 00:09:35,800 Again, that function copies one character at a time. 184 00:09:35,800 --> 00:09:39,239 And then when it hits the terminator, it copies that as well and stops. 185 00:09:40,420 --> 00:09:40,870 That's it. 186 00:09:40,880 --> 00:09:43,109 Now we'll loop through just like we did before. 187 00:09:43,410 --> 00:09:50,770 So we'll go from an unsigned int, i equals 0 while I is less than, we'll 188 00:09:50,770 --> 00:09:58,199 say, std string length of buff by one. 189 00:10:01,540 --> 00:10:05,830 And for each iteration what we'll do is, we'll just simply say buff sub-I 190 00:10:06,200 --> 00:10:15,560 equals, we'll call std to lower, and we'll make the buffs of I lower. 191 00:10:16,600 --> 00:10:20,460 That just makes it a lowercase character, right. 192 00:10:20,460 --> 00:10:23,380 So now we've got what we need to build our temporary object, 193 00:10:23,920 --> 00:10:26,070 temporary to this function that we're going to return. 194 00:10:26,309 --> 00:10:33,970 So mystring temp will initialize it from buff, and we'll return 195 00:10:33,990 --> 00:10:35,690 buff sorry we'll return temp. 196 00:10:36,070 --> 00:10:39,460 Now obviously, we allocated space in here, which we're done with. 197 00:10:39,460 --> 00:10:43,030 So we need to delete buff. 198 00:10:43,809 --> 00:10:44,940 That way we don't leak memory. 199 00:10:45,639 --> 00:10:47,240 And I think that should do it again. 200 00:10:47,250 --> 00:10:49,600 If we have some typos I'll fix them once I compile. 201 00:10:50,140 --> 00:10:52,540 And then the last one we'll do is the concatenation. 202 00:10:55,150 --> 00:10:56,550 So now let's implement this one. 203 00:10:57,000 --> 00:10:59,060 It's going to return a mystring object. 204 00:10:59,240 --> 00:11:02,729 The operator we're overloading is the addition or plus operator, which 205 00:11:02,730 --> 00:11:04,960 means concatenation in this context. 206 00:11:05,609 --> 00:11:07,650 And we've got it's a binary operator, right. 207 00:11:07,650 --> 00:11:10,370 So we've got those two objects again in the parameter list, 208 00:11:10,590 --> 00:11:18,280 the left-hand side and the right-hand side, both references. 209 00:11:20,500 --> 00:11:21,619 Okay, so now what do we do? 210 00:11:21,770 --> 00:11:23,050 Well, let's allocate the space. 211 00:11:23,059 --> 00:11:26,180 Remember, the space needs to be big enough to hold both those strings 212 00:11:26,190 --> 00:11:27,390 since we're going to concatenate. 213 00:11:27,680 --> 00:11:32,799 So we'll just simply say char buffer again, and we'll 214 00:11:32,800 --> 00:11:35,069 create a new character array. 215 00:11:35,840 --> 00:11:36,540 How big is it? 216 00:11:36,550 --> 00:11:46,069 Well, it's the length of left-hand side string plus the length of the 217 00:11:46,070 --> 00:11:49,290 right-hand side string plus one. 218 00:11:51,679 --> 00:11:54,420 That way we've got enough space to put both strings in there. 219 00:11:54,830 --> 00:11:57,199 Now what we do is we just copy the first one over. 220 00:11:57,910 --> 00:12:03,330 We use string copy into buff from the left-hand side object, 221 00:12:04,130 --> 00:12:09,290 and then we concatenate on the end of that using string cat 222 00:12:11,630 --> 00:12:13,419 from the right-hand side object. 223 00:12:15,710 --> 00:12:18,279 Again, we've got what we need to create our object that 224 00:12:18,279 --> 00:12:19,430 we're going to return now. 225 00:12:19,610 --> 00:12:23,500 So we'll create mystring, and we'll just call it temp, and 226 00:12:23,550 --> 00:12:25,200 we'll initialize it with buff. 227 00:12:26,790 --> 00:12:28,580 And let me get rid of that space in there. 228 00:12:30,040 --> 00:12:32,560 Perfect, again, we return temp. 229 00:12:33,210 --> 00:12:36,270 But before we do that, we've got to be sure that we delete the buffer. 230 00:12:36,299 --> 00:12:37,380 So we don't leak memory. 231 00:12:40,350 --> 00:12:41,250 And that should do it. 232 00:12:41,900 --> 00:12:47,289 So let's give this a compile, and we've got a compiler error here. 233 00:12:47,550 --> 00:12:49,090 I need one more colon there. 234 00:12:52,029 --> 00:12:58,329 And I've got an extra parenthesis and see what else we have here, char. 235 00:13:02,340 --> 00:13:03,240 And that should do it. 236 00:13:03,250 --> 00:13:04,380 There's my run. 237 00:13:05,340 --> 00:13:08,680 So what we're doing is we're creating a string Larry, which is Larry with an 238 00:13:08,680 --> 00:13:10,309 uppercase l, and we're displaying it. 239 00:13:10,320 --> 00:13:11,450 There you can see it. 240 00:13:12,449 --> 00:13:16,100 Then we're using the unary minus operator right here. 241 00:13:16,100 --> 00:13:17,190 And we're negating Larry. 242 00:13:17,190 --> 00:13:20,570 What that means is just make Larry with all lowercase letters. 243 00:13:20,580 --> 00:13:22,640 And in this case, we're assigning right back to Larry. 244 00:13:22,980 --> 00:13:27,499 So what happened here is that you can see there he prints out right here, 245 00:13:27,520 --> 00:13:28,660 and we're using move assignment. 246 00:13:28,879 --> 00:13:31,320 So Larry has got a lowercase l now. 247 00:13:31,880 --> 00:13:35,250 And then we've got some some comparison operators 248 00:13:35,250 --> 00:13:36,190 that we're testing out here. 249 00:13:36,450 --> 00:13:39,630 So Larry right now is Larry and Moe is Moe. 250 00:13:39,670 --> 00:13:40,469 Are they the same? 251 00:13:40,530 --> 00:13:41,360 No. 252 00:13:41,590 --> 00:13:43,060 Is Larry the same as Stooge. 253 00:13:43,130 --> 00:13:45,409 Yes, because I assigned Larry to stooge as you can 254 00:13:45,410 --> 00:13:46,450 see, so they're the same. 255 00:13:46,879 --> 00:13:49,610 And then we've got a few more test cases here, which are real simple. 256 00:13:49,870 --> 00:13:54,640 Here Larry plus Moe displays Stooges is Larry plus Moe. 257 00:13:54,870 --> 00:13:57,980 So when I display Stooges, you see here Larry Moe, right. 258 00:13:57,980 --> 00:14:00,180 No space between them because I didn't provide one. 259 00:14:00,969 --> 00:14:03,839 Here two Stooges is Moe plus space plus Larry. 260 00:14:04,190 --> 00:14:06,890 And I display that, there you see Moe and a space and Larry. 261 00:14:07,139 --> 00:14:10,050 And then finally, we're going to change some of these concatenators so 262 00:14:10,430 --> 00:14:12,790 we have Moe space Larry space Curly. 263 00:14:13,250 --> 00:14:14,890 And we've got Moe Larry and Curly. 264 00:14:14,890 --> 00:14:19,350 Notice Larry still has that little lowercase l, and curly is a c-style 265 00:14:19,350 --> 00:14:20,880 string, and it works just fine. 266 00:14:21,670 --> 00:14:22,491 Okay, there you go. 267 00:14:22,491 --> 00:14:26,060 You'll have some more time to practice these in the challenge exercise where 268 00:14:26,060 --> 00:14:29,830 you'll be able to do some overloaded member functions and some overloaded 269 00:14:29,830 --> 00:14:33,479 operators as member functions and others as non-member functions.