Page 263 - Introduction to Microcontrollers Architecture, Programming, and Interfacing of The Motorola 68HC12
P. 263

240                                   Chapter 8 Programming in C and C++


         have ab + ac you can factor out the common term a and write a (b + c), which has
         fewer multiplications. Similarly, if a large number of classes use the same function
         member, such a function member could be reproduced for each. Declaring such a function
         member in one place in a base class would be more statically efficient, where all derived
        classes would inherit it. Also, if an error were discovered and corrected in a base class's
         function member, it is automatically corrected for use in all the derived classes that use
         the common function member. Istack's constructor, using the notation : Cstack(i
         & -1) just after the constructor's name Istack: :istack(char i) before the
        constructor's body in {}, calls the base class's constructor before its own constructor is
        executed. In fact, Istack's constructor does nothing else, as is denoted by the empty
        procedure {}. All derived classes need to declare their constructor, even if that constructor
        does nothing but call its base class's constructor. Other function members can call their
        base's function members by the key word inherited as in inherited:: push {i); or by
        explicitly naming the class, in front of the function call, as in Cstack:: push (i);
            Consider the hypothetical situation where a program can declare classes Cstack and
         Istack. Inside main, are statements Sptr->push(1); and i = Sptr->pull (}; .
        At compile time, either of the objects can be declared for either Cstack or Istack,
        using conditional compilation; for instance, the program on the left:

          void main(){ int i;              void main(){ int i; Cstack *Sptr;
          #ifdef mode                      #ifdef mode
               Cstack. S(1Q);                  Sptr = new Cstack (10);
          #else                            #else
               Istack S(10);                   Sptr = new Istack (10);
          #endif                           #endif
               S.push(l); i = S.pull();        Sptr->push(1); i = Sptr->pull();
           }                               }
        declares S a class Cstack object if mode is #declared, otherwise it is a class
         Istack object. Then the remainder of the program is written unchanged. Alternatively,
        at compile time, a pointer to objects can be blessed for either the Cstack or the
         Istack class. The program above right shows this technique.
            Moreover, a pointer can be blessed to be objects of different classes at run time. At
        the very beginning of main, assume a variable called range denotes the actual
        maximum data size saved in the stack:

        void main(){ int i, range; Cstack *Sptr;
           if(range >= 128) Sptr = new Istack(lO); else Sptr = new Cstack(lO);
           Sptr->push(1); i = Sptr->pull();
         }
        Sptr->push (1); and i = Sptr->pull () ; will use the stack of 8-bit members if the
        range is small enough to save space, otherwise they will use a stack that has enough
        room for each element to hold the larger data, as will be explained shortly.
            Polymorphism means that any two classes can declare the same function member
        name and argument, especially a class and its inherited classes. It means that simple
        intuitive names like push can be used for interchangeable function members of different
        classes. Polymorphism will be used later when we substitute one object for another
   258   259   260   261   262   263   264   265   266   267   268