home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / tutorial / cpptutor / text / chap06.txt < prev    next >
Encoding:
Text File  |  1994-05-15  |  45.4 KB  |  928 lines

  1.  
  2.  
  3.  
  4.                                                         Chapter 6
  5.                                                MORE ENCAPSULATION
  6.  
  7. WHY BOTHER WITH ENCAPSULATION?
  8. -----------------------------------------------------------------
  9. We asked this question earlier, but now that we have a little 
  10. experience, we can provide a much better answer.  Encapsulation 
  11. protects data from accidental corruption, and constructors 
  12. guarantee proper initialization.  Both prevent errors that we are 
  13. very prone to make since we are thinking only about the internals 
  14. of the class when we are writing it.  Later, when we are actually 
  15. using the class, we have no need to concern ourselves with the 
  16. internal structure or operation, but can spend our energies using 
  17. the class to solve the overall problem we are working on.  As you 
  18. may guess, there is a lot more to learn about the use and 
  19. benefits of classes so we will dive right into some new topics.
  20.  
  21. The purpose of this chapter is to illustrate how to use some of 
  22. the traditional aspects of C or C++ with classes and objects.  
  23. Pointers to an object as well as pointers within an object will 
  24. be illustrated.  Arrays embedded within an object, and an array 
  25. of objects will be illustrated.  Since objects are simply another 
  26. C++ data construct, all of these things are possible and can be 
  27. used if needed.
  28.  
  29. In order to have a systematic study, we will use the program 
  30. named BOXES1.CPP from the last chapter as a starting point and we 
  31. will add a few new constructs to it for each example program.  
  32. You will recall that it was a very simple program with the class 
  33. definition, the class implementation, and the main program all in 
  34. one file.  This was selected as a starting point because we will 
  35. eventually make changes to all parts of the program and it will 
  36. be convenient to have it all in a single file for illustrative 
  37. purposes.  It must be kept in mind however that the proper way to 
  38. use these constructs is to separate them into the three files as 
  39. was illustrated in BOX.H, BOX.CPP, and BOXES2.CPP in the last 
  40. chapter.  This allows the implementor of box to supply the user 
  41. with only the interface, namely  BOX.H.  Not giving him the 
  42. implementation file named BOX.CPP, is practicing the technique of 
  43. information hiding.  As we have said many times, it seems silly 
  44. to break up such a small program into three separate files, and 
  45. it is sort of silly.  The last chapter of this tutorial will 
  46. illustrate a program large enough to require dividing the program 
  47. up into many separate files.
  48.  
  49.  
  50. AN ARRAY OF OBJECTS
  51. -----------------------------------------------------------------
  52. Examine the file named OBJARRAY.CPP for our    ==================
  53. first example of an array of objects.  This       OBJARRAY.CPP
  54. file is nearly identical to the file named     ==================
  55. BOX1.CPP until we come to line 44 where an 
  56.  
  57.                                                          Page 6-1
  58.  
  59.                                    Chapter 6 - More Encapsulation
  60.  
  61. array of 4 boxes are declared.  Recalling the operation 
  62. of the constructor you will remember that each of the four box 
  63. objects will be initialized to the values defined within the 
  64. constructor since each box will go through the constructor as 
  65. they are declared.  In order to declare an array of objects, a 
  66. constructor for that object must not require any parameters.  (We 
  67. have not yet illustrated a constructor with initializing 
  68. parameters, but we will in the next program.)  This is an 
  69. efficiency consideration since it would probably be an error to 
  70. initialize all elements of an array of objects to the same value.  
  71. We will see the results of executing the constructor when we 
  72. compile and execute the file later.
  73.  
  74. Line 49 defines a for loop that begins with 1 instead of the 
  75. normal starting index for an array leaving the first object, 
  76. named group[0], to use the default values stored when the 
  77. constructor was called.  You will observe that sending a message 
  78. to one of the objects uses the same construct as is used for any 
  79. object.  The name of the array followed by its index in square 
  80. brackets is used to send a message to one of the objects in the 
  81. array.  This is illustrated in line 50 and the operation of that 
  82. code should be clear to you.  The other method is called in the 
  83. output statement in lines 57 and 58 where the area of the four 
  84. boxes in the group array are listed on the monitor.
  85.  
  86. Another fine point should be mentioned.  The integer variable 
  87. named index is declared in line 49 and is still available for use 
  88. in line 56 since we have not yet left the enclosing block which 
  89. begins in line 43 and extends to line 65.
  90.  
  91.  
  92. DECLARATION AND DEFINITION OF A VARIABLE
  93. -----------------------------------------------------------------
  94. An extra variable was included for illustration, the one named 
  95. extra_data in line seven.  Since the keyword static is used to 
  96. modify this variable in line 7, it is an external variable and 
  97. only one copy of this variable will ever exist.  All seven 
  98. objects of this class share a single copy of this variable which 
  99. is global to the objects defined in line 44.
  100.  
  101. The variable is actually only declared here which says it will 
  102. exist somewhere, but it is not defined.  A declaration says the 
  103. variable will exist and gives it a name, but the definition 
  104. actually defines a place to store it somewhere in the computers 
  105. memory space.  By definition, a static variable can be declared 
  106. in a class header but it cannot be defined there, so it is 
  107. usually defined in the implementation file.  In this case it is 
  108. defined in line 16 and can then be used throughout the class.
  109.  
  110. Figure 6-1 is a graphical representation of some of the 
  111. variables.  Note that the objects named large, group[0], 
  112. group[1], and group[2] are not shown but they also share the 
  113.  
  114.  
  115.                                                          Page 6-2
  116.  
  117.                                    Chapter 6 - More Encapsulation
  118.  
  119. variable named extra_data.  They are not shown in order to 
  120. simplify the picture and enhance the clarity.
  121.  
  122. Line 23 of the constructor sets the single global variable to 1 
  123. each time an object is declared.  Only one assignment is 
  124. necessary so the other six are actually wasted code.  To 
  125. illustrate that there is only one variable shared by all objects 
  126. of this class, the method to read its value also increments it.  
  127. Each time it is read in lines 60 through 64, it is incremented 
  128. and the result of the execution proves that there is only a 
  129. single variable shared by all objects of this class.  You will 
  130. also note that the method named get_extra() is defined within 
  131. the class declaration so it will be assembled into the final 
  132. program as inline code.
  133.  
  134. You will recall the 2 static variables we declared in lines 16 
  135. and 17 of DATE.H in chapter 5 of this tutorial.  We defined them 
  136. in lines 9 and 10 of DATE.CPP and overlooked a complete 
  137. explanation of what they did at that time.  The declaration and 
  138. definition of these variables should be considered a good example 
  139. of the proper place to put these constructs in your classes.
  140.  
  141. Be sure you understand this program and especially the static 
  142. variable, then compile and execute it to see if you get the same 
  143. result as listed at the end of the program.
  144.  
  145.  
  146. A STRING WITHIN AN OBJECT
  147. -----------------------------------------------------------------
  148. Examine the program named OBJSTRNG.CPP for    ===================
  149. our first example of an object with an           OBJSTRING.CPP
  150. embedded string.  Actually, the object does   ===================
  151. not have an embedded string, it has an 
  152. embedded pointer, but the two work so closely together that we 
  153. can study one and understand both.  You will notice that line 7 
  154. contains a pointer to a string named line_of_text.  The 
  155. constructor contains an input parameter which is a pointer to a 
  156. string which will be copied to the string named line_of_text 
  157. within the constructor.  We could have defined the variable 
  158. line_of_text as an actual array in the class, then used strcpy() 
  159. to copy the string into the object and everything would have 
  160. worked the same, but we will leave that as an exercise for you at 
  161. the end of this chapter.  It should be pointed out that we are 
  162. not limited to passing a single parameter to a constructor.  Any 
  163. number of parameters can be passed, as will be illustrated later.
  164.  
  165. You will notice that when the three boxes are declared this time, 
  166. we supply a string constant as an actual parameter with each 
  167. declaration which is used by the constructor to assign the string 
  168. pointer some data to point to.  When we call get_area() in lines 
  169. 48 through 53, we get the message displayed and the area 
  170. returned.  It would be prudent to put these operations in 
  171. separate methods since there is no apparent connection between 
  172.  
  173.                                                          Page 6-3
  174.  
  175.                                    Chapter 6 - More Encapsulation
  176.  
  177. printing the message and calculating the area, but it was written 
  178. this way to illustrate that it can be done.  What this really 
  179. says is that it is possible to have a method that has a side 
  180. effect, the message output to the monitor, and a return value, 
  181. the area of the box.  However, as we discussed in chapter 4 when 
  182. we studied DEFAULT.CPP, the order of evaluation is sort of funny, 
  183. so we broke each line into two lines.
  184.  
  185. After you understand this program, compile and execute it.
  186.  
  187.  
  188. AN OBJECT WITH AN INTERNAL POINTER
  189. -----------------------------------------------------------------
  190. The program named OBJINTPT.CPP is our first    ==================
  191. example program with an embedded pointer          OBJINTPT.CPP
  192. which will be used for dynamic allocation of   ==================
  193. data.  In line 7 we declare a pointer to an 
  194. integer variable, but it is only a pointer, there is no storage 
  195. associated with it.  The constructor therefore allocates an 
  196. integer type variable on the heap for use with this pointer in 
  197. line 21.  It should be clear to you that the three objects 
  198. created in line 45 each contain a pointer which points into the 
  199. heap to three different locations.  Each object has its own 
  200. dynamically allocated variable for its own private use.  Moreover 
  201. each has a value of 112 stored in its dynamically allocated data 
  202. because line 22 stores that value in each of the three locations, 
  203. once for each call to the constructor.
  204.  
  205. In such a small program, there is no chance that we will exhaust 
  206. the heap, so no test is made for unavailable memory.  In a real 
  207. production program, it would be expedient to test that the value 
  208. of the returned pointer is not NULL to assure that the data 
  209. actually did get allocated.
  210.  
  211. The method named set() has three parameters associated with it 
  212. and the third parameter is used to set the value of the new 
  213. dynamically allocated variable.  There are two messages passed, 
  214. one to the small box and one to the large box.  As before, the 
  215. medium box is left with its default values.
  216.  
  217. The three areas are displayed followed by the three stored values 
  218. in the dynamically allocated variables, and we finally have a 
  219. program that requires a destructor in order to be completely 
  220. proper.  If we simply leave the scope of the objects as we do 
  221. when we leave the main program, we will leave the three 
  222. dynamically allocated variables on the heap with nothing pointing 
  223. to them.  They will be inaccessible and will therefore represent 
  224. wasted storage on the heap.  For that reason, the destructor is 
  225. used to delete the variable which the pointer named point is 
  226. referencing, as each object goes out of existence.  In this case, 
  227. lines 37 and 38 assign zero to variables that will be 
  228. automatically deleted.  Even though these lines of code really do 
  229. no good, they are legal statements.
  230.  
  231.                                                          Page 6-4
  232.  
  233.                                    Chapter 6 - More Encapsulation
  234.  
  235. Actually, in this particular case, the variables will be 
  236. automatically reclaimed when we return to the operating system 
  237. because all program cleanup is done for us at that time.  If this 
  238. were a function that was called by another function however, the 
  239. heap space would be wasted.  This is an illustration of good 
  240. programming practice, that of cleaning up after yourself when you 
  241. no longer need some dynamically allocated variables.
  242.  
  243. One other construct should be mentioned again, that of the inline 
  244. method implementations in line 11 and 12.  As we mentioned in 
  245. chapter 5 and repeated earlier in this chapter, inline functions 
  246. can be used where speed is of the utmost in importance since the 
  247. code is assembled inline rather than by actually making a method 
  248. call.  Since the code is defined as part of the declaration, the 
  249. system will assemble it inline, and a separate implementation for 
  250. these methods is not needed.  If the inline code is too involved, 
  251. the compiler is allowed to ignore the inline request and will 
  252. actually assemble it as a separate method, but it will do it 
  253. invisibly to you and will probably not even tell you about it.
  254.  
  255. Remember that we are interested in using information hiding and 
  256. inline code prevents hiding of the implementation, putting it out 
  257. in full view.  Many times you will be more interested in speeding 
  258. up a program than you are in hiding a trivial implementation.  
  259. Since most inline methods are trivial, you should feel free to 
  260. use the inline code construct wherever it is expedient.  Be sure 
  261. to compile and execute this program.
  262.  
  263.  
  264. A DYNAMICALLY ALLOCATED OBJECT
  265. -----------------------------------------------------------------
  266. Examine the file named OBJDYNAM.CPP for our    ==================
  267. first look at a dynamically allocated object.     OBJDYNAM.CPP
  268. This is not any different than any other       ==================
  269. dynamically allocated object, but an example 
  270. is always helpful.  In line 39 we declare a pointer to an object
  271. of type box and since it is only a pointer with nothing to point
  272. to, we dynamically allocate an object for it in line 44, with the 
  273. object being created on the heap just like any other dynamically 
  274. allocated variable.  When the object is created in line 44, the 
  275. constructor is called automatically to assign values to the two 
  276. internal storage variables.  Note that the constructor is not 
  277. called when the pointer is declared since there is nothing to 
  278. initialize.  It is called when the object is allocated.
  279.  
  280. Reference to the components of the object are handled in much the 
  281. same way that structure references are made, through use of the 
  282. pointer operator as illustrated in lines 50 through 52.  Of 
  283. course you can use the pointer dereferencing method without the 
  284. arrow such as (*point).set(12, 12); as a replacement for line 51 
  285. but the arrow notation is much more universal and should be used.  
  286. Finally, the object is deleted in line 54 and the program 
  287. terminates.  If there were a destructor for this class, it would 
  288.  
  289.                                                          Page 6-5
  290.  
  291.                                    Chapter 6 - More Encapsulation
  292.  
  293. be called as part of the delete statement to clean up the object 
  294. prior to deletion.
  295.  
  296. You have probably noticed by this time that the use of objects is 
  297. not much different from the use of structures.  Be sure to 
  298. compile and execute this program after you have studied it 
  299. thoroughly.
  300.  
  301.  
  302. AN OBJECT WITH A POINTER TO ANOTHER OBJECT
  303. -----------------------------------------------------------------
  304. The program named OBJLIST.CPP contains an       =================
  305. object with an internal reference to another       OBJLIST.CPP
  306. object of its own class.  This is the           =================
  307. standard structure used for a singly linked 
  308. list and we will keep the use of it very simple in this program.
  309.  
  310. The constructor contains the statement in line 21 which assigns 
  311. the pointer the value of NULL to initialize the pointer.  This is 
  312. a good idea for all of your programming, don't allow any pointer 
  313. to point off into space, but initialize all pointers to something.  
  314. By assigning the pointer within the constructor, you guarantee 
  315. that every object of this class will automatically have its 
  316. pointer initialized.  It will be impossible to overlook the 
  317. assignment of one of these pointers.
  318.  
  319. Two additional methods are declared in lines 12 and 13 with the 
  320. one in line 13 having a construct we have not yet mentioned in 
  321. this tutorial.  This method returns a pointer to an object of the 
  322. box class.  As you are aware, you can return a pointer to a 
  323. struct in standard C, and this is a parallel construct in C++.  
  324. The implementation in lines 48 through 51 returns the pointer 
  325. stored within the object.  We will see how this is used when we 
  326. get to the actual program.
  327.  
  328. An extra pointer named box_pointer is declared in the main 
  329. program for use later and in line 66 we make the embedded pointer 
  330. within the small box point to the medium box.  Line 67 makes the 
  331. embedded pointer within the medium box point to the large box.  
  332. We have effectively generated a linked list with three elements.  
  333. In line 69 we make the extra pointer point to the small box.  
  334. Continuing in line 70 we use it to refer to the small box and 
  335. update it to the value contained in the small box which is the 
  336. address of the medium box.  We have therefore traversed from one 
  337. element of the list to another by sending a message to one of the 
  338. objects.  If line 70 were repeated exactly as shown, it would 
  339. cause the extra pointer to refer to the large box, and we would 
  340. have traversed the entire linked list which is only composed of 
  341. three elements.  Figure 6-2 is a graphical representation of the 
  342. data space following execution of  line 69.  Note that only a 
  343. portion of each object is actually depicted here to keep it 
  344. simple.
  345.  
  346.  
  347.                                                          Page 6-6
  348.  
  349.                                    Chapter 6 - More Encapsulation
  350.  
  351. ANOTHER NEW KEYWORD this
  352. -----------------------------------------------------------------
  353. Another new keyword is available in C++, the keyword this.  The 
  354. word this is defined within any object as being a pointer to the 
  355. object in which it is contained.  It is implicitly declared as   
  356. class_name *this; and is initialized to point to the object for 
  357. which the member function is invoked.  This pointer is most 
  358. useful when working with pointers and especially with a linked 
  359. list when you need to reference a pointer to the object you are 
  360. inserting into the list.  The keyword this is available for this 
  361. purpose and can be used in any object.  Actually the proper way 
  362. to refer to any variable within a list is through use of the 
  363. predefined pointer this, by writing this->variable_name, but the 
  364. compiler assumes the pointer is used, and we can simplify every 
  365. reference by omitting the pointer.  Use of the keyword this is 
  366. not illustrated in a program at this point, but will be used in 
  367. one of the larger example programs later in this tutorial.
  368.  
  369. You should study this program until you understand it completely 
  370. then compile and execute it in preparation for our next example 
  371. program.
  372.  
  373.  
  374. A LINKED LIST OF OBJECTS
  375. -----------------------------------------------------------------
  376. The next example program in this chapter is     =================
  377. named OBJLINK.CPP and is a complete example        OBJLINK.CPP
  378. of a linked list written in object oriented     =================
  379. notation.  This program is very similar to
  380. the last one.  In fact it is identical until we get to the main 
  381. program.  You will recall that in the last program the only way 
  382. we had to set or use the embedded pointer was through use of the 
  383. two methods named point_at_next() and get_next() which are listed 
  384. in lines 40 through 51 of the present program.  We will use these 
  385. to build up our linked list then traverse and print the list.  
  386. Finally, we will delete the entire list to free the space on the 
  387. heap.
  388.  
  389. In lines 56 through 58 we declare three pointers for use in the 
  390. program.  The pointer named start will always point to the 
  391. beginning of the list, but temp will move down through the list 
  392. as we create it.  The pointer named box_pointer will be used for 
  393. the creation of each object.  We execute the loop in lines 61 
  394. through 69 to generate the list where line 62 dynamically 
  395. allocates a new object of the box class and line 63 fills it 
  396. with nonsense data for illustration.  If this is the first 
  397. element in the list, the start pointer is set to point to this 
  398. element, but if elements already exist, the last element in the 
  399. list is assigned to point to the new element.  In either case, 
  400. the temp pointer is assigned to point to the last element of the 
  401. list, in preparation for adding another element if there is 
  402. another element to be added.
  403.  
  404.  
  405.                                                          Page 6-7
  406.  
  407.                                    Chapter 6 - More Encapsulation
  408.  
  409. In line 72, the pointer named temp is caused to point to the 
  410. first element and it is used to increment its way through the 
  411. list by updating itself in line 75 during each pass through the 
  412. loop.  When temp has the value of NULL, which it gets from the 
  413. last element of the list, we are finished traversing the list.
  414.  
  415. Finally, we delete the entire list by starting at the beginning 
  416. and deleting one element each time we pass through the loop in 
  417. lines 79 through 84.
  418.  
  419. A careful study of the program will reveal that it does indeed 
  420. generate a linked list of ten elements, each element being an 
  421. object of class box.  The length of this list is limited by the 
  422. practicality of how large a list we desire to print out, but it 
  423. could be lengthened to many thousands of these simple elements 
  424. provided you have enough memory available to store them all.
  425.  
  426. Once again, the success of the dynamic allocation is not checked 
  427. as it should be in a correctly written program.  Be sure to 
  428. compile and execute this example program.
  429.  
  430.  
  431. NESTING OBJECTS
  432. -----------------------------------------------------------------
  433. Examine the program named NESTING.CPP for an    =================
  434. example of nesting classes which results in        NESTING.CPP
  435. nested objects.  A nested object could be       =================
  436. illustrated with your computer in a rather 
  437. simple manner.  The computer itself is composed of many items 
  438. which work together but work entirely differently, such as a 
  439. keyboard, a disk drive, and a power supply.  The computer is 
  440. composed of these very dissimilar items and it is desirable to 
  441. discuss the keyboard separately from the disk drive because they 
  442. are so different.  A computer class could be composed of several 
  443. objects that are dissimilar by nesting the dissimilar classes 
  444. within the computer class.
  445.  
  446. If however, we wished to discuss disk drives, we may wish to 
  447. examine the characteristics of disk drives in general, then 
  448. examine the details of a hard disk, and the differences of floppy 
  449. disks.  This would involve inheritance because much of the data 
  450. about both drives could be characterized and applied to the 
  451. generic disk drive then used to aid in the discussion of the 
  452. other three.  We will study inheritance in the next three 
  453. chapters, but for now we will look at the embedded or nested 
  454. class.
  455.  
  456. This example program contains a class named box which contains an 
  457. object of another class embedded within it in line 16, the 
  458. mail_info class.  It is depicted graphically in figure 6-3.  This 
  459. object is available for use only within the class implementation 
  460. of box because that is where it is defined.  The main program has 
  461. objects of class box defined but no objects of class mail_info, 
  462.  
  463.                                                          Page 6-8
  464.  
  465.                                    Chapter 6 - More Encapsulation
  466.  
  467. so the mail_info class cannot be referred to in the main program.  
  468. In this case, the mail_info class object is meant to be used 
  469. internally to the box class and one example is given in line 21 
  470. where a message is sent to the label.set() method to initialize 
  471. the variables.  Additional methods could be used as needed, but 
  472. these are given as an illustration of how they can be called.
  473.  
  474. Of prime importance is the fact that there are never any objects 
  475. of the mail_info class declared directly in the main program, 
  476. they are inherently declared when the enclosing objects of class 
  477. box are declared.  Of course objects of the mail_info class could 
  478. be declared and used in the main program if needed, but they are 
  479. not in this example program.  In order to be complete, the box 
  480. class should have one or more methods to use the information 
  481. stored in the object of the mail_info class.  Study this program 
  482. until you understand the new construct, then compile and 
  483. execute it.
  484.  
  485. If the class and the nested classes require parameter lists for 
  486. their respective constructors an initialization list can be 
  487. given.  This will be discussed and illustrated later in this 
  488. tutorial.
  489.  
  490.  
  491. OPERATOR OVERLOADING
  492. -----------------------------------------------------------------
  493. The example file named OPOVERLD.CPP contains   ==================
  494. examples of overloading operators.  This          OPOVERLD.CPP
  495. allows you to define a class of objects and    ==================
  496. redefine the use of the normal operators.  
  497. The end result is that objects of the new class can be used in as 
  498. natural a manner as the predefined types.  In fact, they seem to 
  499. be a part of the language rather than your own add-on.
  500.  
  501. In this case we overload the + operator and the * operator, with 
  502. the declarations in lines 10 through 12, and the definitions in 
  503. lines 16 through 40.  The methods are declared as friend 
  504. functions so we can use the double parameter functions as listed.  
  505. If we did not use the friend construct, the function would be a 
  506. part of one of the objects and that object would be the object to 
  507. which the message was sent.  Including the friend construct 
  508. allows us to separate this method from the object and call the 
  509. method with infix notation.  Using this technique, it can be writ-
  510. ten as object1 + object2 rather than object1.operator+(object2).  
  511. Also, without the friend construct we could not use an 
  512. overloading with an int type variable for the first parameter 
  513. because we can not send a message to an integer type variable 
  514. such as int.operator+(object).  Two of the three operator 
  515. overloadings use an int for the first parameter so it is 
  516. necessary to declare them as friend functions.
  517.  
  518.  
  519.  
  520.  
  521.                                                          Page 6-9
  522.  
  523.                                    Chapter 6 - More Encapsulation
  524.  
  525. There is no upper limit to the number of overloadings for any 
  526. given operator.  Any number of overloadings can be used provided 
  527. the parameters are different for each particular overloading.
  528.  
  529. The header in line 16 illustrates the first overloading where the 
  530. + operator is overloaded by giving the return type followed by 
  531. the keyword operator and the operator we wish to overload.  The 
  532. two formal parameters and their types are then listed in the 
  533. parentheses and the normal function operations are given in the 
  534. implementation of the function in lines 18 through 21.  The 
  535. observant student will notice that the implementation of the 
  536. friend functions are not actually a part of the class because the 
  537. class name is not prepended onto the method name in line 16.  
  538. There is nothing unusual about this implementation, it should be 
  539. easily understood by you at this point.  For purposes of 
  540. illustration, some silly mathematics are performed in the method 
  541. implementation, but any desired operations can be done.
  542.  
  543. The biggest difference occurs in line 56 where this method is 
  544. called by using the infix notation instead of the usual message 
  545. sending format.  Since the variables small and medium are objects 
  546. of the box class, the system will search for a way to use the 
  547. + operator on two objects of class box and will find it in the 
  548. overloaded operator+ method we have just discussed.  The 
  549. operations within the method implementation can be anything we 
  550. need them to be, and they are usually much more meaningful than 
  551. the silly math included here.
  552.  
  553. In line 58 we ask the system to add an int type constant to an 
  554. object of class box, so the system finds the other overloading of 
  555. the + operator beginning in line 25 to perform this operation.  
  556. Also in line 60 we ask the system to use the * operator to do 
  557. something to an int constant and an object of class box, which it 
  558. satisfies by finding the method in lines 34 through 40.  Note 
  559. that it would be illegal to attempt to use the * operator the 
  560. other way around, namely large * 4 since we did not define a 
  561. method to use the two types in that order.  Another overloading 
  562. could be given with reversed types, and we could use the reverse 
  563. order in a program.
  564.  
  565. You will notice that when using operator overloading, we are also 
  566. using function name overloading since some of the function names 
  567. are the same.
  568.  
  569. When we use operator overloading in this manner, we actually make 
  570. our programs look like the class is a natural part of the 
  571. language since it is integrated into the language so well.  C++ 
  572. is therefore an extendible language and can be molded to fit the 
  573. mechanics of the problem at hand.
  574.  
  575.  
  576.  
  577.  
  578.  
  579.                                                         Page 6-10
  580.  
  581.                                    Chapter 6 - More Encapsulation
  582.  
  583. OPERATOR OVERLOADING CAVEATS
  584. -----------------------------------------------------------------
  585. Each new topic we study has its pitfalls which must be warned 
  586. against and the topic of operator overloading seems to have the 
  587. record for pitfalls since it is so prone to misuse and has 
  588. several problems.  The overloading of operators is only available 
  589. for classes, you cannot redefine the operators for the predefined 
  590. simple types.  This would probably be very silly anyway since the 
  591. code could be very difficult to read if you changed some of them 
  592. around.
  593.  
  594. The logical and "&&" and the logical or "||" operators can be 
  595. overloaded for the classes you define, but they will not operate 
  596. as short circuit operators.  All members of the logical 
  597. construction will be evaluated with no regard concerning the 
  598. outcome.  Of course the normal predefined logical operators will 
  599. continue to operate as short circuit operators as expected, but 
  600. not the overloaded ones.
  601.  
  602. If the increment "++" or decrement "--" operators are overloaded, 
  603. the system has no way of telling whether the operators are used 
  604. as preincrement or postincrement (or predecrement or 
  605. postdecrement) operators.  Which method is used is 
  606. implementation dependent, so you should use them in such a way 
  607. that it doesn't matter which is used.
  608.  
  609. Be sure to compile and execute OPOVERLD.CPP before continuing on 
  610. to the next example program.
  611.  
  612.  
  613. FUNCTION OVERLOADING IN A CLASS
  614. -----------------------------------------------------------------
  615. Examine the program named FUNCOVER.CPP for an  ==================
  616. example of function name overloading within a     FUNCOVER.CPP
  617. class.  In this program the constructor is     ==================
  618. overloaded as well as one of the methods to 
  619. illustrate what can be done.
  620.  
  621. This file illustrates some of the uses of overloaded names and a 
  622. few of the rules for their use.  You will recall that the 
  623. function selected is based on the number and types of the formal 
  624. parameters only.  The type of the return value is not significant 
  625. in overload resolution.
  626.  
  627. In this case there are three constructors.  The constructor which 
  628. is actually called is selected by the number and types of the 
  629. parameters in the definition.  In line 77 of the main program the 
  630. three objects are declared, each with a different number of 
  631. parameters and inspection of the results will indicate that the 
  632. correct constructor was called based on the number of parameters.
  633.  
  634. In the case of the other overloaded methods, the number and type 
  635. of parameters is clearly used to select the proper method.  You 
  636.  
  637.                                                         Page 6-11
  638.  
  639.                                    Chapter 6 - More Encapsulation
  640.  
  641. will notice that one method uses a single integer and another 
  642. uses a single float type variable, but the system is able to 
  643. select the correct one.  As many overloadings as desired can be 
  644. used provided that all of the parameter patterns are unique.
  645.  
  646. You may be thinking that this is a silly thing to do but it is, 
  647. in fact, a very important topic.  Throughout this tutorial we 
  648. have been using an overloaded operator and you haven't been the 
  649. least confused over it.  It is the cout operator which operates 
  650. as an overloaded function since the way it outputs data is a 
  651. function of the type of its input variable or the field we ask 
  652. it to display.  Many programming languages have overloaded 
  653. output functions so you can output any data with the same 
  654. function name. 
  655.  
  656. Be sure to compile and execute this program.
  657.  
  658.  
  659. SEPARATE COMPILATION
  660. -----------------------------------------------------------------
  661. Separate compilation is available with C++ and it follows the 
  662. identical rules as given for ANSI-C separate compilation.  As 
  663. expected, separately compiled files can be linked together.  
  664. However, since classes are used to define objects, the nature of 
  665. C++ separate compilation is considerably different from that used 
  666. for ANSI-C.  This is because the classes used to create the 
  667. objects are not considered as external variables, but as included 
  668. classes.  This makes the overall program look different from a 
  669. pure ANSI-C program.  Your programs will take on a different 
  670. appearance as you gain experience in C++.
  671.  
  672.  
  673. YOU GET SOME METHODS BY DEFAULT
  674. -----------------------------------------------------------------
  675. Even if you include no constructors or         ==================
  676. operator overloadings you get a few defined       DEFMETHS.CPP
  677. automatically by the compiler.  Examine the    ==================
  678. file named DEFMETHS.CPP which will illustrate 
  679. those methods provided by the compiler, and why you sometimes 
  680. can't use the defaults but need to write your own to do the job 
  681. the defaults were intended to do for you.
  682.  
  683. Before we actually look at the program, we will list a few rules 
  684. that all compiler writers must follow in order to deliver a 
  685. useful implementation of C++.  First we will state the rules, 
  686. then take a closer look at them and the reason for their 
  687. existence.
  688.  
  689. 1.  If no constructors are defined by the writer of a class, the 
  690.     compiler will automatically generate a default constructor 
  691.     and a copy constructor.  Both of these constructors will be 
  692.     defined for you shortly.
  693.  
  694.  
  695.                                                         Page 6-12
  696.  
  697.                                    Chapter 6 - More Encapsulation
  698.  
  699. 2.  If the class author includes any constructor in the class, 
  700.     the default constructor will not be supplied by the 
  701.     constructor.
  702.  
  703. 3.  If the class author does not include a copy constructor, the 
  704.     compiler will generate one, but if the writer includes a copy 
  705.     constructor, the compiler will not generate one 
  706.     automatically.
  707.  
  708. 4.  If the class author includes an assignment operator, the 
  709.     compiler will not include one automatically, otherwise it 
  710.     will generate a default assignment operator.
  711.  
  712. Any class declared and used in a C++ program must have some way 
  713. to construct an object because the compiler, by definition, must 
  714. call a constructor when we define an object.  If we don't provide 
  715. a constructor, the compiler itself will generate one that it can 
  716. call during construction of the object.  This is the default 
  717. constructor and we have used it unknowingly in a lot of our 
  718. example programs.  The default constructor does not initialize 
  719. any of the member variables, but it sets up all of the internal 
  720. class references it needs, and calls the base constructor or 
  721. constructors if they exist.  We haven't studied inheritance yet, 
  722. but we will in the next chapter of this tutorial so we will know 
  723. then what base classes are all about.  Line 11 of the present 
  724. program contains a default constructor which is called when you 
  725. define an object with no parameters.  In this case, the 
  726. constructor is necessary because we have an embedded string in 
  727. the class that requires a dynamic allocation and an 
  728. initialization of the string to the null string.  It will take 
  729. little thought to see that our constructor is much better than 
  730. the default constructor which would leave us with an 
  731. uninitialized pointer.
  732.  
  733. The default constructor is used in line 78 of this example 
  734. program.
  735.  
  736.  
  737. THE COPY CONSTRUCTOR
  738. -----------------------------------------------------------------
  739. The copy constructor is generated automatically for you by the 
  740. compiler if you fail to define one yourself.  It is used to copy 
  741. the contents of an object to a new object during construction of 
  742. that new object.  If the compiler generates it for you, it will 
  743. simply copy the contents of the original into the new object as a 
  744. byte by byte copy, which may not be what you want.  For simple 
  745. classes with no pointers, that is usually sufficient, but in the 
  746. present example program, we have a pointer as a class member so a 
  747. byte by byte copy would copy the pointer from one to the other 
  748. and they would both be pointing to the same allocated member.  
  749. For this program, we declared our own copy constructor in line 14 
  750. and implemented it in lines 34 to 39.  A careful study of the 
  751. implementation will reveal that the new class will indeed be 
  752.  
  753.                                                         Page 6-13
  754.  
  755.                                    Chapter 6 - More Encapsulation
  756.  
  757. identical to the original, but the new class has its own string 
  758. to work with.  Since both constructors contain dynamic 
  759. allocation, we must assure that the allocated data is destroyed 
  760. when we are finished with the objects, so a destructor is 
  761. mandatory as implemented in lines 50 through 53 of the present 
  762. example program.  The copy constructor is used in line 84 of the 
  763. current example program.
  764.  
  765.  
  766. THE ASSIGNMENT OPERATOR
  767. -----------------------------------------------------------------
  768. It is not too obvious, but an assignment operator is required for 
  769. this program also, because the default assignment operator simply 
  770. copies the source object to the destination object byte by byte.  
  771. This would result the same problem we had with copy constructor.  
  772. The assignment operator is declared in line 17 and defined in 
  773. lines 41 through 49 where we deallocate the old string in the 
  774. existing object prior to allocating room for the new text and 
  775. copying the text from the source object into the new object.  The 
  776. assignment operator is used in line 91.
  777.  
  778. It should be fairly obvious to the student that when a class is 
  779. defined which includes any sort of dynamic allocation, the above 
  780. three methods should be included in addition to the proper 
  781. destructor.  If any of the four entities are omitted, the program 
  782. may have terribly erratic behavior.  Be sure to compile and 
  783. execute this example program.
  784.  
  785.  
  786. A PRACTICAL EXAMPLE
  787. -----------------------------------------------------------------
  788. Using the inline keyword with a class member   ==================
  789. can cause a bit of difficulty unless you            PHRASE.H
  790. understand how the compiler uses the inline    ==================
  791. code definition to perform the inline code 
  792. insertion.  Examine the header file named PHRASE.H which includes 
  793. some inline methods.  These are included as an illustration of 
  794. one means of defining the inline methods in a clean way that the 
  795. compiler can use efficiently.  When any implementation uses this 
  796. class, it must have access to the inline implementation in order 
  797. to insert the proper inline code for the member functions.  One 
  798. way to do this is to put all of the inline methods in a separate 
  799. file named with the INL extension, then including that file into 
  800. the end of the .H file as shown here.  This makes all of the 
  801. inline code available for the compiler while compiling files 
  802. that use this class.
  803.  
  804. The example file named PHRASE.INL contains     ==================
  805. all of the inline code for this class.  If         PHRASE.INL
  806. this class had methods that were not           ==================
  807. inlined, they could be packaged into a file 
  808. named PHRASE.CPP in the usual manner.  Note that for illustrative 
  809.  
  810.  
  811.                                                         Page 6-14
  812.  
  813.                                    Chapter 6 - More Encapsulation
  814.  
  815. purposes, all of the methods were declared inline, so there is no 
  816. implementation file for this class.
  817.  
  818. The file named USEPHRAS.CPP uses the phrase    ==================
  819. class defined in the last two example files.      USEPHRAS.CPP
  820. It is plain to see that this class is no       ==================
  821. different than any others we have studied.  
  822. It simply illustrates a way to package inline code in a simple 
  823. and very efficient manner.
  824.  
  825.  
  826. ANOTHER PRACTICAL EXAMPLE
  827. -----------------------------------------------------------------
  828. We come again to the practical part of this lesson where we study 
  829. a practical class that can actually be used in a program but is 
  830. still simple enough for the student to completely understand.
  831.  
  832. In the last chapter we studied the date          ================
  833. class and in this chapter we will study a             TIME.H
  834. simple time class.  You should begin by          ================
  835. studying the file named TIME.H which will 
  836. look very similar to the date class header.  The only major 
  837. difference in this class from the date class is the overloaded 
  838. constructors and methods.  The program is a very practical 
  839. example that illustrates very graphically that many constructor 
  840. overloadings are possible.
  841.  
  842. The implementation for the time class is       ==================
  843. given in the file named TIME.CPP.  Once             TIME.CPP
  844. again, the code is very simple and you         ==================
  845. should have no problem understanding this 
  846. example in its entirety.  It should be pointed out that three of 
  847. the four overloadings actually call the fourth so that the code 
  848. did not have to be repeated four times.  This is a perfectly good 
  849. coding practice and illustrates that other member functions can 
  850. be called from within the implementation.
  851.  
  852. The example program named USETIME.CPP is a      =================
  853. very simple program that uses the time class       USETIME.CPP
  854. in a very rudimentary way as an illustration    =================
  855. for you.  You should be able to understand 
  856. this program in a very short time.  It will be to your advantage 
  857. to completely understand the practical example programs given at 
  858. the end of the last chapter and the end of this chapter.  As 
  859. mentioned above, we will use the time class and the date class 
  860. as the basis for both single and multiple inheritance in the 
  861. next three chapters.
  862.  
  863.  
  864. WHAT SHOULD BE THE NEXT STEP?
  865. -----------------------------------------------------------------
  866. At this point you have learned enough C++ to write meaningful 
  867. programs and it would be to your advantage to stop studying and 
  868.  
  869.                                                         Page 6-15
  870.  
  871.                                    Chapter 6 - More Encapsulation
  872.  
  873. begin using the knowledge you have gained.  Because C++ is an 
  874. extension to ANSI-C, it can be learned in smaller pieces than 
  875. would be required if you are learning a completely new language.  
  876. You have learned enough to study and completely understand the 
  877. example program given in chapter 12, the Flyaway adventure game.  
  878. You should begin studying this program now.
  879.  
  880. One of your biggest problems is learning to think in terms of 
  881. object oriented programming.  It is not a trivial problem if you 
  882. have been programming in procedural languages for any significant 
  883. length of time.  However, it can be learned by experience, so you 
  884. should begin trying to think in terms of classes and objects 
  885. immediately.  Your first project should use only a small number 
  886. of objects and the remainder of code can be completed in standard 
  887. procedural programming techniques.  As you gain experience, you 
  888. will write more of the code for any given project using classes 
  889. and objects but every project will eventually be completed in 
  890. procedural code.
  891.  
  892. After you have programmed for a while using the techniques 
  893. covered up to this point in the tutorial, you can continue on to 
  894. the next few chapters which will discuss inheritance and virtual 
  895. functions.
  896.  
  897.  
  898. PROGRAMMING EXERCISES
  899. -----------------------------------------------------------------
  900. 1.  Modify OBJDYNAM.CPP to make the objects named small and 
  901.     medium pointers, then dynamically allocate them prior to 
  902.     using them.
  903.  
  904. 2.  Modify the loop in line 61 of OBJLINK.CPP so that the loop 
  905.     will store 1000 elements in the list before stopping.  You 
  906.     will probably wish to remove the printout from line 74 so the 
  907.     program will stop in a reasonable time.  You may also get an 
  908.     integer overflow indicated by wrong answers if you send a 
  909.     message to get_area() with such large numbers.  That will 
  910.     depend upon your compiler.  You should also add a test to 
  911.     assure that the memory did not become exhausted after each 
  912.     dynamic allocation.
  913.  
  914. 3.  Write a program that uses both the date and time classes in a 
  915.     meaningful manner.  No answer will be given in the ANSWERS 
  916.     directory for this exercise since it is so straight forward.
  917.     These classes can be used in all of your future C++ programs 
  918.     to time stamp the time and date of execution.
  919.  
  920.  
  921.  
  922.  
  923.  
  924.  
  925.  
  926.  
  927.                                                         Page 6-16
  928.