


                                                              Chapter 6
                                                     MORE ENCAPSULATION

      The purpose of this chapter is to illustrate how to use some of the
      traditional aspects of C or C++ with classes and objects.  Pointers
      to an object as well as pointers within an object will be
      illustrated.  Arrays embedded within an object, and an array of
      objects will be illustrated.  Since objects are simply another C
      data construct, all of these things are possible and can be used
      if needed.

      In order to have a systematic study, we will use the program named
      BOXES1.CPP from the last chapter as a starting point and we will
      add a few new constructs to it for each example program.  You will
      recall that it was a very simple program with the class definition,
      the class implementation, and the main calling program all in one
      file.  This was selected as a starting point because we will
      eventually make changes to all parts of the program and it will be
      convenient to have it all in a single file for illustrative
      purposes.  It must be kept in mind however that the proper way to
      use these constructs is to separate them into the three files as
      was illustrated in BOX.HPP, BOX.CPP, and BOXES2.CPP in the last
      chapter.  This allows the implementor of box to supply the user
      with only the interface, namely  BOX.HPP.  Not giving him the
      implementation file named BOX.CPP, is practicing the technique of
      information hiding.

      As we have said many times, it seems silly to break up such a small
      program into three separate files, and it is sort of silly.  The
      last chapter of this tutorial will illustrate a program large
      enough to require dividing the program up into separate files.


      AN ARRAY OF OBJECTS
      _________________________________________________________________

      Examine the file named OBJARRAY.CPP for our      ================
      first example of an array of objects.  This file   OBJARRAY.CPP
      is identical to the file named BOX1.CPP until we ================
      come to line 41 where an array of 4 boxes are
      declared.

      Recalling the operation of the constructor you will remember that
      each of the four box objects will be initialized to the values
      defined within the constructor since each box will go through the
      constructor as they are declared.  In order to declare an array of
      objects, a constructor for that object must not require any
      parameters.  (We have not yet illustrated a constructor with
      initializing parameters, but we will in the next program.)  This
      is an efficiency consideration since it would probably be an error
      to initialize all elements of an array of objects to the same
      value.  We will see the results of executing the constructor when
      we compile and execute the file later.

                                                               Page 6-1
      
                                         Chapter 6 - More Encapsulation

      Line 46 defines a for loop that begins with 1 instead of the normal
      starting index for an array leaving the first object, named
      group[0], to use the default values stored when the constructor was
      called.  You will observe that sending a message to one of the
      objects uses the same construct as is used for any object.  The
      name of the array followed by its index in square brackets is used
      to send a message to one of the objects in the array.  This is
      illustrated in line 47 and the operation of that code should be
      clear to you.  The other method is called in the output statement
      in lines 54 and 55 where the area of the four boxes in the group
      array are listed on the monitor.

      Another fine point should be pointed out.  The integer variable
      named index is declared in line 46 and is still available for use
      in line 53 since we have not yet left the enclosing block which
      begins in line 40 and extends to line 62.

      An extra variable was included for illustration, the one named
      extra_data in line seven.  Since the keyword static is used to
      modify this variable in line 7, it is an external variable and only
      one copy of this variable will ever exist.  All seven objects of
      this class share a single copy of this variable which is global to
      the objects defined in line 41.  Line 20 of the constructor sets
      the single global variable to 1 each time an object is declared.
      Only one assignment is necessary so the other six are actually
      wasted code.  To illustrate that there is only one variable shared
      by all objects of this class, the method to read its value also
      increments it.  Each time it is read in lines 57 through 61, it is
      incremented and the result of the execution proves that there is
      only a single variable shared by all objects of this class.  You
      will also note that this method is declared within the class
      declaration so it will be assembled into the final program as
      inline code.

      Be sure you understand this program and especially the static
      variable, then compile and execute it to see if you get the same
      result as listed at the end of the program.


      A STRING WITHIN AN OBJECT
      _________________________________________________________________

      Examine the program named OBJSTRNG.CPP for our   ================
      first example of an object with an embedded        OBJSTRNG.CPP
      string.  Actually, the object does not have an   ================
      embedded string, it has an embedded pointer, but
      the two work so closely together that we can
      study one and understand both.

      You will notice that line 7 contains a pointer to char named
      line_of_text.  The constructor contains an input parameter which
      is a pointer to a string and will be assigned to the stored pointer
      named line_of_text within the constructor.  We could have defined

                                                               Page 6-2
      
                                         Chapter 6 - More Encapsulation

      the variable line_of_text as an actual array in the class, then
      used strcpy() to copy the string into the object and everything
      would have worked the same, but we will leave that as an exercise
      for you at the end of this chapter.  It should be clear to you that
      if a single parameter can be passed to a constructor, any number
      can be passed.

      You will notice that when the three boxes are declared this time,
      we supply a string constant as an actual parameter with each
      declaration which is used by the constructor to assign the string
      pointer some data to point to.  When we call get_area() in lines
      48 through 53, we get the message displayed and the area returned.
      It would be prudent to put these operations in separate methods
      since there is no apparent connection between printing the message
      and calculating the area, but it was written this way to illustrate
      that it can be done.  What this really says is that it is possible
      to have a method that has a side effect, the message output to the
      monitor, and a return value, the area of the box.  However, as we
      discussed in chapter 4 when we studied DEFAULT.CPP, the order of
      evaluation is sort of funny, so we broke each line into two lines.

      After you understand this program, compile and execute it.


      AN OBJECT WITH AN INTERNAL POINTER
      _________________________________________________________________

      The program named OBJINTPT.CPP is our first      ================
      example program with an embedded pointer which     OBJINTPT.CPP
      will be used for dynamic allocation of data.     ================

      In line 7 we declare a pointer to an integer
      variable, but it is only a pointer, there is no storage associated
      with it.  The constructor therefore allocates an integer type
      variable on the heap for use with this pointer in line 21.  It
      should be clear to you that the three objects created in line 45
      each contain a pointer which points into the heap to three
      different locations.  Each object has its own dynamically allocated
      variable for its own private use.  Moreover each has a value of 112
      stored in its dynamically allocated data because line 22 stores
      that value in each of the three locations, once for each call to
      the constructor.

      In such a small program, there is no chance that we will exhaust
      the heap, so no test is made for unavailable memory.  In a real
      production program, it would be expedient to test that the value
      of the returned pointer is not NULL to assure that the data
      actually did get allocated.

      The method named set() has three parameters associated with it and
      the third parameter is used to set the value of the new dynamically
      allocated variable.  There are two messages passed, one to the
      small box and one to the large box.  As before, the medium box is
      left with its default values.

                                                               Page 6-3
      
                                         Chapter 6 - More Encapsulation


      The three areas are displayed followed by the three stored values
      in the dynamically allocated variables, and we finally have a
      program that requires a destructor in order to be completely
      proper.  If we simply leave the scope of the objects as we do when
      we leave the main program, we will leave the three dynamically
      allocated variables on the heap with nothing pointing to them.
      They will be inaccessible and will therefore represent wasted
      storage on the heap.  For that reason, the destructor is used to
      delete the three variables as their respective objects go out of
      existence.  In this case, lines 37 and 38 assign values to
      variables that will be automatically deleted.  Even though these
      lines of code really do no good, they are legal statements.

      Actually, in this particular case, the three variables will be
      automatically reclaimed when we return to the operating system
      because all program cleanup is done for us at that time.  If this
      were a function that was called by another function however, the
      heap space would be wasted.  This is an illustration of good
      programming practice, that of cleaning up after yourself when you
      no longer need some dynamically allocated variables.

      One other construct should be mentioned once again, that of the
      inline method implementations in line 11 and 12.  As we mentioned
      in chapter 5 and repeated earlier in this chapter, inline functions
      can be used where speed is of the utmost in importance since the
      code is assembled inline rather than by actually making a method
      call.  Since the code is defined as part of the declaration, the
      system will assemble it inline, and a separate implementation for
      these methods is not needed.  Remember that if the inline code is
      too involved, the compiler is allowed to ignore the inline request
      and actually assemble it as a separate method, but it will do it
      invisibly to you and will probably not even tell you about it.

      Remember that we are interested in using information hiding and
      inline code prevents hiding of the implementation, putting it out
      in full view.  Many times you will be more interested in speeding
      up a program than you are in hiding a trivial implementation.
      Since most inline methods are trivial, feel free to use the inline
      code construct.

      Be sure to compile and execute this program.



      A DYNAMICALLY ALLOCATED OBJECT
      _________________________________________________________________

      Examine the file named OBJDYNAM.CPP for our      ================
      first look at a dynamically allocated object.      OBJDYNAM.CPP
      This is not any different than any other         ================
      dynamically allocated object, but an example is
      always helpful.


                                                               Page 6-4
      
                                         Chapter 6 - More Encapsulation

      In line 39 we declare a pointer to an object of type box and since
      it is only a pointer with nothing to point to, we dynamically
      allocate an object for it in line 44, with the object being created
      on the heap just like any other dynamically allocated variable.
      When the object is created in line 44, the constructor is called
      automatically to assign values to the two internal storage
      variables.  Note that the constructor is not called when the
      pointer is declared since there is nothing to initialize.  It is
      called when the object is allocated.

      Reference to the components of the object are handled in much the
      same way that structure references are made, through use of the
      pointer operator as illustrated in lines 50 through 52.  Of course
      you can use the pointer dereferencing method without the arrow such
      as (*point).set(12, 12); as a replacement for line 51 but the arrow
      notation is much more universal and should be used.  Finally, the
      object is deleted in line 54 and the program terminates.  If there
      were a destructor for this class, it would be called as part of the
      delete statement to clean up the object prior to deletion.

      You have probably noticed by this time that the use of objects is
      not much different from the use of structures.  Be sure to compile
      and execute this program after you have studied it thoroughly.


      AN OBJECT WITH A POINTER TO ANOTHER OBJECT
      _________________________________________________________________

      The program named OBJLIST.CPP contains an object  ===============
      with an internal reference to another object of     OBJLIST.CPP
      its own class.  This is the standard structure    ===============
      used for a singly linked list and we will keep
      the use of it very simple in this program.

      The constructor contains the statement in line 21 which assigns the
      pointer the value of NULL to initialize the pointer.  This is a
      good idea for all of your programming, don't allow any pointer to
      point off into space, but initialize all pointers to something.
      By assigning the pointer within the constructor, you guarantee that
      every object of this class will automatically have its pointer
      initialized.  It will be impossible to overlook the assignment of
      one of these pointers.

      Two additional methods are declared in lines 12 and 13 with the one
      in line 13 having a construct we have not yet mentioned in this
      tutorial.  This method returns a pointer to an object of the box
      class.  As you are aware, you can return a pointer to a struct in
      standard C, and this is a parallel construct in C++.  The
      implementation in lines 48 through 51 returns the pointer stored
      within the object.  We will see how this is used when we get to the
      actual program.

      An extra pointer named box_pointer is declared in the main program
      for use later and in line 66 we make the embedded pointer within

                                                               Page 6-5
      
                                         Chapter 6 - More Encapsulation

      the small box point to the medium box, and in line 67 we make the
      embedded pointer within the medium box point to the large box.  We
      have effectively generated a linked list with three elements.  In
      line 69 we make the extra pointer point to the small box.
      Continuing in line 70 we use it to refer to the small box and
      update it to the value contained in the small box which is the
      address of the medium box.  We have therefore traversed from one
      element of the list to another by sending a message to one of the
      objects.  If line 70 were repeated exactly as shown, it would cause
      the extra pointer to refer to the large box, and we would have
      traversed the entire linked list which is only composed of three
      elements.


      ANOTHER NEW KEYWORD this
      _________________________________________________________________

      Another new keyword is available in C++, the keyword this.  The
      word this is defined within any object as being a pointer to the
      object in which it is contained.  It is implicitly declared as;

         class_name *this;

      and is initialized to point to the object for which the member
      function is invoked.  This pointer is most useful when working with
      pointers and especially with a linked list when you need to
      reference a pointer to the object you are inserting into the list.
      The keyword this is available for this purpose and can be used in
      any object.  Actually the proper way to refer to any variable
      within a list is through use of the predefined pointer this, by
      writing this->variable_name, but the compiler assumes the pointer,
      and we can simplify every reference by omitting the pointer.  Use
      of the keyword this is not illustrated in a program at this point,
      but will be used in one of the larger example programs later in
      this tutorial.

      You should study this program until you understand it completely
      then compile and execute it in preparation for our next example
      program.


      A LINKED LIST OF OBJECTS
      _________________________________________________________________

      The next example program in this chapter is       ===============
      named OBJLINK.CPP and is a complete example of      OBJLINK.CPP
      a linked list written in object oriented          ===============
      notation.

      This program is very similar to the last one.  In fact it is
      identical until we get to the main program.  You will recall that
      in the last program the only way we had to set or use the embedded
      pointer was through use of the two methods named point_at_next()
      and get_next() which are listed in lines 40 through 51 of the

                                                               Page 6-6
      
                                         Chapter 6 - More Encapsulation

      present program.  We will use these to build up our linked list
      then traverse and print the list.  Finally, we will delete the
      entire list to free the space on the heap.

      In lines 56 to 58 we declare three pointers for use in the program.
      The pointer named start will always point to the beginning of the
      list, but temp will move down through the list as we create it.
      The pointer named box_pointer will be used for the creation of each
      box.  We execute the loop in lines 61 through 69 to generate the
      list where line 62 dynamically allocates a new object of the box
      class and line 63 fills it with nonsense data for illustration.
      If this is the first element in the list, the start pointer is set
      to point to this element, but if elements already exist, the last
      element in the list is assigned to point to the new element.  In
      either case, the temp pointer is assigned to point to the last
      element of the list, in preparation for adding another element if
      there is another element to be added.

      In line 72, the pointer named temp is pointed to the first element
      and it is used to increment its way through the list by updating
      itself in line 75 during each pass through the loop.  When temp has
      the value of NULL, which it gets from the last element of the list,
      we are finished traversing the list.

      Finally, we delete the entire list by starting at the beginning and
      deleting one element each time we pass through the loop in lines
      79 through 84.

      A careful study of the program will reveal that it does indeed
      generate a linked list of ten elements, each element being an
      object of class box.  The length of this list is limited by the
      practicality of how large a list we desire to print out, but it
      could be lengthened to many thousands of these simple elements
      provided you have enough memory available to store them all.

      Once again, the success of the dynamic allocation is not checked
      as it should be in a correctly written program.  Be sure to compile
      and execute this example program.



      NESTING OBJECTS
      _________________________________________________________________

      Examine the program named NESTING.CPP for an      ===============
      example of nesting classes which results in         NESTING.CPP
      nested objects.  A nested object could be         ===============
      illustrated with your computer in a rather
      simple manner.  The computer itself is composed
      of many items which work together but work entirely differently,
      such as a keyboard, a disk drive, and a power supply.  The computer
      is composed of these very dissimilar items and it is desireable to
      discuss the keyboard separately from the disk drive because they
      are so different.  A computer class could be composed of several

                                                               Page 6-7
      
                                         Chapter 6 - More Encapsulation

      objects that are dissimilar by nesting the dissimilar classes
      within the computer class.

      If however, we wished to discuss disk drives, we may wish to
      examine the characteristics of disk drives in general, then examine
      the details of a hard disk, then the differences of floppy disks,
      and finally bernolli drives.  This would involve inheritance
      because much of the data about all three drives could be
      characterized and applied to the generic disk drive then used to
      aid in the discussion of the other three.  We will study
      inheritance in the next three chapters, but for now we will look
      at the embedded or nested class.

      This example program contains a class named box which contains an
      object of another class embedded within it in line 16, the
      mail_info class.  This object is available for use only within the
      class implementation of box because that is where it is defined.
      The main program has objects of class box defined but no objects
      of class mail_info, so the mail_info class cannot be referred to
      in the main program.  In this case, the mail_info class object is
      meant to be used internally to the box class and one example is
      given in line 21 where a message is sent to the label.set() method
      to initialize the variables.  Additional methods could be used as
      needed, but these are given as an illustration of how they can be
      called.

      Of prime importance is the fact that there are never any objects
      of the mail_info class declared directly in the main program, they
      are inherently declared when the enclosing objects of class box are
      declared.  Of course objects of the mail_info class could be
      declared and used in the main program if needed, but they are not
      in this example program.  In order to be complete, the box class
      should have one or more methods to use the information stored in
      the object of the mail_info class.  Study this program until you
      understand the new construct, then compile and execute it.

      If the class and the nested classes require parameter lists for
      their respective constructors an initialization list can be given.
      This is a very advanced technique, and it is rarely needed, so it
      is beyond the scope of this tutorial.  See Bjarne Stroustrup's book
      for further details if you need more information on the use of this
      technique.


      OPERATOR OVERLOADING
      _________________________________________________________________

      The example file named OPOVERLD.CPP contains     ================
      examples of overloading operators.  This allows    OPOVERLD.CPP
      you to define a class of objects and redefine    ================
      the use of the normal operators.  The end result
      is that objects of the new class can be used in
      as natural a manner as the predefined types.  In fact, they seem
      to be a part of the language rather than your own add-on.

                                                               Page 6-8
      
                                         Chapter 6 - More Encapsulation


      In this case we overload the + operator and the * operator, with
      the declarations in lines 10 through 12, and the definitions in
      lines 16 through 40.  The methods are declared as friend functions
      so we can use the double parameter functions as listed.  If we did
      not use the friend construct, the function would be a part of one
      of the objects and that object would be the object to which the
      message was sent.  Including the friend construct allows us to
      separate this method from the object and call the method with infix
      notation.  Using this technique, it can be written as object1 +
      object2 rather than object1.operator+(object2).  Also, without the
      friend construct we could not use an overloading with an int type
      variable for the first parameter because we can not send a message
      to an integer type variable such as int.operator+(object).  Two of
      the three operator overloadings use an int for the first parameter
      so it is necessary to declare them as friend functions.

      The header in line 16 illustrates the first overloading where the
      + operator is overloaded by giving the return type followed by the
      keyword operator and the operator we wish to overload.  The two
      formal parameters and their types are then listed in the
      parentheses and the normal function operations are given in the
      implementation of the function in lines 18 through 21.  There is
      nothing unusual about this implementation, it should be easily
      understood by you at this point.  For purposes of illustration,
      some silly mathematics are performed in the method implementation,
      but any desired operations can be done.

      The biggest difference occurs in line 56 where this method is
      called by using the infix notation instead of the usual message
      sending format.  Since the variables small and medium are objects
      of the box class, the system will search for a way to use the +
      operator on two objects of class box and will find it in the
      overloaded operator+ method we have just discussed.  The operations
      within the method implementation can be anything we need them to
      be, and they are usually much more meaningful than the silly math
      included here.

      In line 58 we ask the system to add an int type constant to an
      object of class box, so the system finds the other overloading of
      the + operator beginning in line 25 to perform this operation.
      Also in line 60 we ask the system to use the * operator to do
      something to an int constant and an object of class box, which it
      satisfies by finding the method in lines 34 through 40.  Note that
      it would be illegal to attempt to use the * operator the other way
      around, namely large * 4 since we did not define a method to use
      the two types in that order.  Another overloading could be given
      with reversed types, and we could use the reverse order in a
      program.

      You will notice that when using operator overloading, we are also
      using function name overloading since some of the function names
      are the same.


                                                               Page 6-9
      
                                         Chapter 6 - More Encapsulation

      When we use operator overloading in this manner, we actually make
      our programs look like the class is a natural part of the language
      since it is integrated into the language so well.  C++ is therefore
      an extendible language and can be molded to fit the mechanics of
      the problem at hand.


      OPERATOR OVERLOADING CAVEATS
      _________________________________________________________________

      Each new topic we study has its pitfalls which must be warned
      against and the topic of operator overloading seems to have the
      record for pitfalls since it is so prone to misuse and has several
      problems.  The overloading of operators is only available for
      classes, you cannot redefine the operators for the predefined
      simple types.  This would probably be very silly anyway since the
      code could be very difficult to read if you changed some of them
      around.

      The logical and (&&) and the logical or (||) operators can be
      overloaded for the classes you define, but they will not operate
      as short circuit operators.  All members of the logical
      construction will be evaluated with no regard concerning the
      outcome.  Of course the normal predefined logical operators will
      continue to operate as short circuit operators as expected, but not
      the overloaded ones.

      If the increment (++) or decrement (--) operators are overloaded,
      the system has no way of telling whether the operators are used as
      preincrement or postincrement operators.  Which method is used is
      implementation dependent, so you should use them in such a way that
      it doesn't matter which is used.

      Be sure to compile and execute OPOVERLD.CPP before continuing on
      to the next example program.


      FUNCTION OVERLOADING IN A CLASS
      _________________________________________________________________

      Examine the program named FUNCOVER.CPP for an    ================
      example of function name overloading within a      FUNCOVER.CPP
      class.  In this program the constructor is       ================
      overloaded as well as one of the methods to
      illustrate what can be done.

      This file illustrates some of the uses of overloaded names and a
      few of the rules for their use.  You will recall that the function
      selected is based on the number and types of the formal parameters,
      and the type of the return value.

      In this case there are three constructors.  The constructor which
      is actually called is selected by the number and types of the
      parameters in the definition.  In line 77 of the main program the

                                                              Page 6-10
      
                                         Chapter 6 - More Encapsulation

      three objects are declared, each with a different number of
      parameters and inspection of the results will indicate that the
      correct constructor was called based on the number of parameters.
      Since a constructor does not have a return value, according to the
      definition of the C++ language, it cannot be a part of the
      selection criteria of a constructor.

      In the case of the other overloaded methods, the number and type
      of parameters is clearly used to select the proper method.  You
      will notice that one method uses a single integer and another uses
      a single float type variable, but the system is able to select the
      correct one.  As many overloadings as desired can be used provided
      that all of the parameter patterns are unique.

      You may be thinking that this is a silly thing to do but it is, in
      fact, a very important topic.  Throughout this tutorial we have
      been using an overloaded operator and you haven't been the least
      confused over it.  It is the cout operator which operates as an
      overloaded function since the way it outputs data is a function of
      the type of its input variable or the field we ask it to display.
      Many programming languages have overloaded output functions so you
      can output any data with the same function name.

      Be sure to compile and execute FUNCOVER.CPP.


      SEPARATE COMPILATION
      _________________________________________________________________

      Separate compilation is available with C++ and it follows the
      identical rules as given for ANSI-C separate compilation.  As
      expected, separately compiled files can be linked together.
      However, since classes are used to define objects, the nature of
      C++ separate compilation is considerably different from that used
      for ANSI-C.  This is because the classes used to create the objects
      are not considered as external variables, but as included classes.
      This makes the overall program look different from a pure ANSI-C
      program.

      As we have been declaring and using classes in these last two
      chapters, we have been including the classes with the #include
      preprocessor directive rather than by using the ANSI-C extern
      keyword.  Your programs will take on a different appearance as you
      gain experience in C++.


      WHAT SHOULD BE THE NEXT STEP?
      _________________________________________________________________

      At this point you have learned enough C++ to write meaningful
      programs and it would be to your advantage to stop studying and
      begin using the knowledge you have gained.  Because C++ is an
      extension to ANSI-C, it can be learned in smaller pieces than would
      be required if you are learning a completely new language.  You

                                                              Page 6-11
      
                                         Chapter 6 - More Encapsulation

      have learned enough to study and completely understand the example
      program given in chapter 12, the Flyaway adventure game.  You
      should begin studying this program now.

      One of your biggest problems is learning to think in terms of
      object oriented programming.  It is not a trivial problem if you
      have been programming in procedural languages for any significant
      length of time.  However, it can be learned by experience, so you
      should begin trying to think in terms of classes and objects
      immediately.  Your first project should use only a small number of
      objects and the remainder of code can be completed in standard C
      using procedural methods.  As you gain experience, you will write
      more of the code for any given project using classes and objects
      but every project will eventually be completed in procedural code.

      After you have programmed for a while using the techniques covered
      up to this point in the tutorial, you can continue on to the next
      few chapters which will discuss inheritance and virtual functions.


      PROGRAMMING EXERCISES
      _________________________________________________________________

      1.   Rewrite OBJSTRNG.CPP to use an array instead of only a pointer
           to the array and copy the string in the constructor.  Add
           another method to allow you to change the value stored in the
           string by sending a message from the main program and use the
           new method to change the value stored in each of the three
           objects.

      2.   Modify OBJDYNAM.CPP to make the objects named small and medium
           pointers, then dynamically allocate them prior to using them.

      3.   Modify the loop in line 61 of OBJLINK.CPP so that the loop
           will store 1000 elements in the list before stopping.  You
           will probably wish to remove the printout from line 74 so the
           program will stop in a reasonable time.  You may also get an
           integer overflow indication if you send a message to
           get_area() with such large numbers.  That will depend upon
           your compiler.  You should also add a test to assure that the
           memory did not become exhausted after each dynamic allocation.














                                                              Page 6-12

