February 15, 2002
Reading assignment:
  Deitel and Deitel - 7.3, 7.4, 7.6
  -or-
  Wang

Review and Warm-up
  1. What is the output of this program?  Draw a memory map to help yourself
     figure it out.

     int main()
     {
         float arr[5]={2.2, 4.4, 6.6, 8.8, 11.11};
         float *fp=&arr[3];
         float **fpp=&fp;
         cout << arr << arr[1]
              << fp << fp[1] << *fp << &*fp
              << *(*fpp+2) << *fpp << **fpp << (*fpp)[0];
     } 
     Answer:
     arr: whatever the address of arr happens to be
     arr[1]: 4.4
     fp: the address of arr + 3*sizeof float
     fp[1]: 11.11
     *fp: 8.8
     &*fp: same as fp
     *(*fpp+2): indeterminate, since it's past the end of the array arr
     *fpp: same as fp - address of arr+3*sizeof float
      **fpp: 8.8
     (*fpp)[0]: 8.8

More on composition
  - Let's implement the Person class we discussed last time.
    header file: person.h, source file: person.cpp and test file: testperson.cpp
  - Note that the constructor has no default arguments and is not overloaded.
    This is not ideal for the users of this class, for they must initialize
    all Person variables when they are defined.
  - Note that some of the data members are themselves objects
  - The constructors for the member objects are called before the Person can
    be created - the compiler automatically does this.
  - We can specify initialization values for these member objects in the
    constructor.  Notice how this is done in the Person constructor
  - Note that a destructor is provided.  The destructor for the member objects
    is called before the destructor for the Person object.  The compiler
    automatically handles this.
  - Note that the update function is overloaded to take either c-style strings
    or string objects