 So, we will discuss the rational class definition and implementation in some greater details. I have added a couple of things to the rational class definition. This is different from the rational class defined in Cohen's book. You will see a lot of similarities and you will also see differences. So, please note down the definitions and the implementation details of the rational class as I am doing it here and compare that with the rational class definition and implementation given in the Cohen's book. This is to tell you that there is no single unique way in which you can define a class although objects of the class are expected to have exactly similar or identical behavior. The implementation could differ. With this, we go ahead with the discussion on the rational operations. We had briefly discussed this main program which operates upon rational numbers. As I said, when you try to design a class and try to define member functions of the class, you would like to have a clear idea of what kind of interface you want between your programs and the member functions of the class. It is not uncommon, therefore, to imagine the functionality in your mind and try writing some kind of a main program first. This need not be the final main program that you will write. This is a draft. Of course, what I am presenting is a program which actually works correctly. It has been tested but it is possible for you to write just a draft main program. The primary objective here is to identify the interfaces between your program and the class member functions. Int G is just an integer variable. At this juncture, you do not know what it is for. I will explain that. But you will notice that I am defining rational C1, rational C2, 3, 4, C3, 1, 3, C4, C5. Notice that I am therefore implying that the class name is rational which defines a rational type object and that I am defining various objects. I am also defining some initial values for those objects. Obviously, there should be constructors in my definition which will permit such initial values to be allocated. We of course note that our rational numbers are always in the form of A and B, where A is the numerator and B is the denominator. Any name can be given. Next I am using a function display. I am displaying objects C1, C2 and C3. Clearly, a display function is required and hopefully it is a member function of the class or it is a function which I have written myself along with this program. If this were to be a member function of the class, would it be written like this? So why did you not object when I said that it could be either a member function or a function written by me? Please remember, a member function of the class is invoked only by an object of the class. It cannot be invoked as a standalone function by you and me. This particular example or this particular expression C4 dot r add C2 comma C3 is clearly an example of a member function because C4 is an object of the rational class and therefore whenever I write C4 dot a name, that name must be a member function in the class. You can see clearly that the intention here is to add C2 and C3 which are rational numbers. This is a simple output statement which shows the result of addition and I am saying display C4. I clearly expect that C4 which has been hopefully modified to now contain result of C2 plus C3 would be displayed here. So this should tell you the kind of functionality that I should have in the display function. Obviously display function is not part of the member functions of the object. I have written one more function here C5 r multiply just like r add. So r multiply what is it expected to do? Multiply two numbers, two rational numbers C2 and C3 and it should print the result of the multiplication. Multiplication or in fact addition, any operation on two rationals might result in a rational value of the form a by b which is not in its minimal form. So a and b might have common factors. Is that how you represent rationals? No, rationals are always represented such that the numerator and denominator do not have a common factor. Let us see g represents the common factor amongst all of them. Now either I can extract the individual data elements of the class object C1 or C2 or C3 say a and b and myself do some manipulation here or I can add a new function to the class which will reduce the given rational number a by b to the minimal form. This is the path I have taken in this example. I am saying g is equal to C5 dot reduce. I am assuming that C5 may result in a rational number where the numerator and denominator are not relatively prime. They have a common factor in which case I would like to reduce that and also generally know what was the common factor. Clearly this member function is written such that it will take two rationals sorry it will take one rational which is C5 reduce a by b to the minimal form in the process discover what was the highest common factor and will return that and that is why this function must have a return value of the type integer because the return factor is an integer. So it operates upon a rational and returns an integer. You can see that if g is not equal to 1 that means there was a common factor so rational is not minimal, hcf is g and then I display again by this time I would expect C5 to have been reduced to the minimal. So this in general is my attempt to imagine what kind of interfaces I would need between my main program and the objects of a class. Having done that I can now proceed to define my class and proceed to define the implementation of the class. But first you remember we had a display function so a display function is required to be used because that is supposed to display certain things. Notice that this display function is a void this is a prototype void display rational I don't need to put an object name here in the prototype just the type is sufficient. What it means is that the function display which I am writing will take one rational object as a parameter and this particular line must appear before my main program because it is a function prototype definition. I could of course put the entire function definition ahead of my main program but as I said very often such detailed description of the function could occur in a dot h file somewhere. Minimally what I require is to include this which in turn could again appear in another dot h but if a prototype definition must appear before the main program. The function itself is described here it displays a rational number in two forms either as a by b or as a equivalent floating point number. So I am defining float x int a comma b now here I come across another interface requirement I want to find out what are the two data elements of a rational object what is the numerator what is the denominator but those values are not accessible to me directly in my main program. Please remember that data members are private to an object class. So to every object the data members are private consequently I must have a function which is a public function of that class itself which I can use which in turn can look at those private data member functions and can give those values back to me that is what is written here when I say c dot r components. So rational value has components a and b and this function is clearly an additional interface requirement for me to go to an object and ask it please tell me what are your component value. So I can invoke it on any component on any rational object c which is a parameter here c dot r components a comma b okay is supposed to give me back a and b please note that these a and b although the name may appear same as the one used in the class definition they have nothing to do with those a and b these a and b are integer variables in my program I could very well have written a 1 b 1 or p 1 p 2 or whatever these are two integer numbers all that it means is that I am send I am trying to get r components from this function and then I will print a and b and I will also print equivalent float value you keep with this understanding of the interface definitions we now proceed to define and then implement the rational class we start with the word keyword class rational and then say this is a class 200 rational numbers objects are of the type a by b you can write many more things authored by so-and-so on this date okay part of the project for c s 1 1 whatever whatever all kinds of inline comments that you would like in your like to write in your programs could be written here should be written here in fact earlier we had discussed a version of this rational class implementation I am calling it version v 1 because in this v 1 I am seeing a rational is reduced to a minimal representation such as that a and b are mutually private now I have private data members int a and int b as you already seen I have public member functions first the constructors there is a default constructor rational and a parameterize constructor rational int comma int there are functions for other operations so void r add it takes two rational numbers and as them void r multiply it takes two rational numbers multiply them and sets the calling object to that value please note that these are all member functions which are invoked by an object that is why I say something like c 5 r add c 1 comma c 2 so c 1 comma c 2 are added where the c 5 object which invokes this function actually gets the resultant additional value same thing about multiply and then as I said void r components notice that here I am saying int and int and so far we have seen that whenever I have a pointer in the formal parameter of the function the corresponding value should also be a pointer c plus plus does not require that when you mention say x comma y in the actual parameters and the formal parameters are int and int and then automatically the pointer is that is it is sent by reference so that means that whenever you modify the formal parameters inside this function the corresponding actual parameters will also stand modified so far we had seen the reference passing by reference was by using pointers ok but this is a passing by reference mechanism which is valid in c plus last but not the least is our reduced function the reduced function does not take any parameter why because it works on the object which invokes it so if I say c 4 lot reduce it will take components of c 4 a and b reduce them to a minimal form but it is expected to return something do you remember what it was supposed to return the highest common factor and that is why the return type is mentioned as int so this completes the definition of the class ok we have not yet defined the implementation we have just defined the interface so once again to repeat a class has two aspects to be defined first is the interface definition which will also apart from the public functions it will also include the definition of private data members and any other functions that you may have such as protected functions etc which we shall see later all the constructors destructors whatever whatever everything should be included in the definition but once you define them you have to elaborate on what those public functions do and that elaboration comes in what I call the definition of implementation they should be followed following immediately the class definition you write the class definition and immediately continue with the definition of the member function so here I have the beginning of the definition of the member functions rational colon colon rational this is a constructor obviously it is a default constructor as we saw yesterday or therefore yesterday a is equal to 0 b is equal to 1 is the default value that I am assigned you could assign any default value of your choice this is a parameterized constructor it will expect two integer parameters x and y x will be assigned to the numerator y will be assigned to the denominator as you can see there is one extra care that is being taken here if somebody specifies denominator as 0 will it be a valid rational number no so you would like to take care of it if by mistake somebody defines the value to be 0 I would like to say if y is 0 b is set to 1 otherwise b is set to y so this is a default definition which I am providing here is the rational addition it expects two rational objects r1 and r2 and it calculates the addition value for individual data members of the object which cause this addition function as a equal to this and b equal to this obviously this is the way you will add a by b and c by d for example here is a multiplier function which is very similarly written to the add function it will expect two rational objects as parameters and will calculate the result for the invoking object this is the addition if I want to get the components this is the components please remember what I said last time I am trying to peep into the individual data members of the object I am I want to know them and that is why I am doing it however it is not considered a healthy practice generally you will not return the values of a and b which are the data member elements of the class what you will say is you tell me what you want to do with these values and I will do it if you want to display those values let me do it as the class I would not let you touch those things so you can specify output these components in this form or write these components in this file let me do everything that is related to those but please don't try to peep into those components because they are private data that is how you would like to guard those things in this particular implementation I have violated that principle I have violated that principle because supposedly I am trying to mimic all of you when you try to first learn what classes are and try to implement classes it is quite likely that since you will need to display those values you might think of writing such a nothing is wrong by the way this is perfectly valid c++ program it works correctly it is just that it is not considered a very good professional practice to expose private data members to external however in this case I have a function called r components it takes a pointer to m and pointer to n and returns to integer components of a rational and here is the implementation of the reduce you remember what I said a by b need not be in minimal form so I define a n and b n I define a max factor and g is the one which is to be returned I start with g equal to 1 I start with a n equal to a and b n equal to b now I have to keep on dividing a n and b n by 1 2 3 4 5 6 7 8 9 10 all integer number okay somewhere a number will divide both of them whenever that number divides both of them I should capture that into my factor and of course reduce a and b after that division otherwise some number which is divisible by 4 is also divisible by 2 and you will count 2 and 4 as independent factor which is not correct so you divide by something divide by something divide by something and reduce it and you will get this is the iteration that I have done notice that I am saying max factor equal to a greater than b question mark b colon a so if a is larger than b I set max factor as b if a is smaller than b I set max factor as a obviously the smaller of the two is will be the largest common factor if I run an iteration for i equal to 2 to max factor and I keep finding out please note I have captured the member elements a and b into a n and b n so far I do not want to change a and b direct I'm just checking so I am changing a n and b n and if everything is satisfactory I will assign those values to end the program then continues to check whether n modulo i is 0 and b n modulo i is 0 if i is a common factor then I take that a common factor out I multiply g by r let's say 2 is a common factor I started with g equal to 1 so g will now become 2 and the division by 2 for each of these numbers will reduce a n and b n to the next value suppose 3 is another common factor it will again get divided 3 will get factored into g and so on finally when I come out I will assign a n to a b n to b and return the value of g now I want you to find pick holes in this implementation yes what if it is 4 by 8 so what will happen execute the algorithm so what will be max factor max factor will be smaller of the 2 which is 4 this iteration runs for i equal to 2 so let's say i is equal to 2 at i equal to 2 what will happen both a n and b n are divisible by 2 so a n will now reduce to 2 b n will now reduce to 4 and g will become 2 because 2 has been a common factor now i becomes equal to 3 is 2 divisible by 3 is 4 divisible by 3 no so this remains 2 4 this remains 2 then i becomes equal to 4 that's the last iteration is 2 divisible by 4 no so this remains 2 this remains 4 this remains 2 and at the end this becomes a this becomes b problem you can see that in a simple issue of finding out the greatest common the highest common factor I could do a simple goof up of this guy as you are you will see I have executed this main program once to show the results and the results look perfectly fine because it so happens that the particular rational number which results out of some operation and which I reduce and print is actually reduced correctly because it is not of that this type what is peculiarity of this type there is the same factor which appears many times so it is not just 4 by 8 you can take anything which is a multiple of 2 to the power n for example by something which is also multiple of 2 to the power n okay you will get the first 2 out hopefully if there is a factor of 4 that means you have 8 as a common factor you will come out correct but if you have 2 appearing twice 3 appearing twice it will not work what should be the correction you get the correct solution instead of running the iteration from 2 to max factor you start from the max factor downwards that way you will take out the largest common factor first and if something remains that will be at the lower will it always work nobody is completely saying yes try to construct a counter example but the correct thing we are saying now is our iteration should be for i equal to max factor i greater than equal to 2 i minus minus so this is how I will be able to get I have one more question to add two things I am leaving behind for you to work on a will this always work so think about it later and find out B is this the most optimal algorithm to find out highest common factor anybody who is familiar with a better more efficient technique of finding out common factors should it not be very obvious that I should be dividing should I be dividing by all the numbers in the range okay I will leave that to you you can either go to wikipedia or to any standard book on algorithms and it will tell you the best algorithm or the fastest or the most efficient algorithm to calculate the highest common factor we digress a bit but these are precisely the issues that you should look at when you are implementing a project the first thing is to get the functionality right or whatever problem solution you are thinking of the next before you finalize your project report examine each and every implementation is it written in the most optimal fashion is the program most efficient can it be made better and is it written in an elegant fashion and finally is it written such that others can understand what you have written these are the three parameters on which you should examine any program that you I would like to discuss operator overloading before I call my friends there we know standard operators plus minus star slash module operator we also know comparison operators would it not be nice if I had rational C1 C2 C3 and somewhere in my program I could directly say C3 is equal to C1 plus C2 would you not like such an implementation it is natural it is meaningful because rational number addition is defined conceptually to be very similar to the addition of two integer numbers or two floating point same thing goes for C3 equal to say C1 star C2 same thing goes for if C1 greater than C2 do you agree comparison between two rationals actually is a comparison similar to comparison between two integers or two floating point would you not like to do this one more thing would you not like to say this you see how easy your programs would become and how logical they would read such things are possible in C plus plus in fact C plus plus explicitly provides for you to take normal operators and redefine them to extend their meaning that is called operator overloading all the operators can be redefined like that and now you will note when I say all operators what about these symbols this symbol and this symbol are also operators in C plus plus they are called extraction and insertion operators C in greater greater C1 or C in greater greater anything that greater greater is actually an extraction operator you will remember that C in represented STD in reading from standard input so standard input is a stream of bytes the bytes are coming as you type them on the keyboard and those bytes are to be interpreted those bytes are to be assumed to mean as key values and you have to interpret chunks of those bytes as an integer number floating point number and convert it into internal form that is what C in does so C in operates upon STD in stream and the C in is defined as a stream of type STD in and it has an extraction operator called greater bit similarly C out is defined as an O stream or an output stream and less less is defined as an insertion operate what is C out trying to insert it takes an integer value or a floating point value converts it into a nice ASCII string which represents that value and inserts it into the output stream with blanks in between whatever whatever use so C plus plus treats these also as operators and therefore it permits overloading of these operators as well it has certain key we had certain rules for example a binary operator meaning an operator which requires two operands must have two operands even when you overload it similarly a unary operator if it is used in a unary sense must have one operand common sense caveats there is a whole lot of description of how operators are to be overloaded I will just show you how the addition operator is overloaded in this particular case and then we can expand that or extend that to other thing so first I need an interface definition please note that operator overloading is to be defined as part of member functions of the class only so after you have described data elements which are private data members of the object class then you describe member functions of the class which do for example additions of practice whatever whatever you decided reduce other operations and then you can define extensions to operators this is the definition that will appear in your main definition of the interface rational operator plus this operator is a key word you can't write anything else here the word O P E R A T O R is the keyword it's a reserve word so the operator word tells C plus plus that I am not defining any new function by a different name I am actually trying to redefine one of your standard operator and what is that operator without any intervening blank you write that up that operator will usually be one simple or two symbols plus minus star slash percent greater greater less less whatever you write must be a valid operator in C plus plus which is extendable as I said most operators are extendable but not necessarily all operators are extended it's also an additional matter whether the extension of the meaning of that operator makes sense in the context of the class that you are defined for example you have defined an employee class and you have employee IDs now can you add employee 1 plus employee 2 obviously not it won't make any sense okay so it would make common sense it should make sense semantic sense also in the context of what you are doing observe what are the two parameters const rational and R const rational and S so there is a rational parameter 1 rational parameter 2 what is extremely important is to remember that there is a left parameter and there is a right parameter because you are overloading the plus operator the meaning of this is that the actual invocation where you normally say C 5 dot reduce or C 5 dot add rational add something C 1 comma C 2 you won't be saying any such thing because there's no function name there's a symbol name and this symbol when overloaded still means that it has to be used exactly the as it is used in the context of other ordinary mortal variables like in or real that means if R and S are two rational objects for which I am going to invoke this operator in my C program C plus plus program I'll always write R plus S that's all the plus now becomes a function call but this plus function has two parameters one physically appearing on the left of it another physically appearing on the right of it so this is a very peculiar kind of function call semantically it's a function call so when the plus operator is seen with two sides with one rational and another rational then automatically this overloaded function will be invoked what is the implementation of that overloaded function in this particular case I have an overloaded function cons rational and R cons rational and S the result of this has to be a rational so the object which invokes this should have this rational this particular implementation is faulty as you will see later I'm deliberately giving you a faulty interpretation implementation I want you to read the coons book and see the other the correct implementation that he has given you can implement it in multiple ways the overloading of function here it is just an idea for you to get how overloading can be defined and how overloading can be implemented so just as this one will come in the definition and this one will come in the implementation so here I am saying rational operator plus cons rational and R cons rational and S this returns rational so R1 plus say R plus S is supposed to return a rational number so I am defining a rational number as result rational object as result now once I have result then result has A and B components I am setting a component of result as this and B component of result as this now I say return result so this result which is a rational number will be written the usage therefore of this kind of operation will simply be in my main program somewhere I will have to say C5 is equal to C1 plus so when I say C1 plus C2 the compiler recognizes that I have a plus symbol on either side of it or two rational numbers it will then examine whether I have overloaded plus defined in that class if I don't have overloaded plus defined it will give an error but if I have it defined it will invoke that definition with that definition the parameters will go to this function the first value C1 now please note when I say first value and second value it in the context of plus symbol means the value appearing to its left and value appearing to its right and these two will go to these two parameters using this it will calculate this the result which is returned will replace C1 plus C2 as any computational result does for a sub expression suppose I had a integer value m would it be correct to say m plus C1 will this be a correct statement many people are silent you're not convinced so somebody thinks that there may be some sense okay how many of you think that it could still be interpreted correctly nobody then only a few people said no why others are not confident of course it is incorrect it is incorrect for two reasons number one it does not make any semantic sense to us please note that if C5 is 3 by 2 and if m is 5 then 5 plus 3 by 2 as a meaning in mathematical set but in a programming sense it has no meaning because the plus operator which has been extended in its definition the extended definition applies only when you're trying to use it for adding two rational numbers not otherwise if you want to operate upon m you love to form a rational number using m as numerator and one as denominator and then only then you can use the resulting rational number for adding using this overloaded okay with this we'll stop