Implementing the ATM System from Its UML Design

We are now ready to begin implementing the ATM system. We first convert the classes in the diagrams of Fig. 23.1 and Fig. 23.2 into C++ header files. This code will represent the “skeleton” of the system. In Section 23.3, we modify the header files to incorporate the object-oriented concept of inheritance. In Section 23.4, we present the complete working C++ code for our model.

As an example, we begin to develop the header file for class Withdrawal from our design of class Withdrawal in Fig. 23.1. We use this figure to determine the attributes and operations of the class. We use the UML model in Fig. 23.2 to determine the associations among classes. We follow the following five guidelines for each class:

1. Use the name in the first compartment of a class in a class diagram to define the class in a header file (Fig. 23.3). Use #ifndef, #define and #endif preprocessor directives to prevent the header from being included more than once in a program.


 1   // Fig. 23.3: Withdrawal.h
 2   // Definition of class Withdrawal that represents a withdrawal transaction
 3   #ifndef WITHDRAWAL_H
 4   #define WITHDRAWAL_H
 5
 6   class Withdrawal
 7   {
 8   }; // end class Withdrawal
 9
10   #endif // WITHDRAWAL_H


Fig. 23.3. Definition of class Withdrawal enclosed in preprocessor wrappers.

2. Use the attributes located in the class’s second compartment to declare the data members. For example, the private attributes accountNumber and amount of class Withdrawal yield the code in Fig. 23.4.


 1   // Fig. 23.4: Withdrawal.h
 2   // Definition of class Withdrawal that represents a withdrawal transaction
 3   #ifndef WITHDRAWAL_H
 4   #define WITHDRAWAL_H
 5
 6   class Withdrawal
 7   {
 8   private:
 9      // attributes                                       
10      int accountNumber; // account to withdraw funds from
11      double amount; // amount to withdraw                
12   }; // end class Withdrawal
13
14   #endif // WITHDRAWAL_H


Fig. 23.4. Adding attributes to the Withdrawal class header file.

3. Use the associations described in the class diagram to declare references (or pointers, where appropriate) to other objects. For example, according to Fig. 23.2, Withdrawal can access one object of class Screen, one object of class Keypad, one object of class CashDispenser and one object of class BankDatabase. Class Withdrawal must maintain handles on these objects to send messages to them, so lines 19–22 of Fig. 23.5 declare four references as private data members. In the implementation of class Withdrawal in Section 23.4, a constructor initializes these data members with references to actual objects. Lines 6–9 #include the header files containing the definitions of classes Screen, Keypad, CashDispenser and BankDatabase so that we can declare references to objects of these classes in lines 19–22.


 1   // Fig. 23.5: Withdrawal.h
 2   // Definition of class Withdrawal that represents a withdrawal transaction
 3   #ifndef WITHDRAWAL_H
 4   #define WITHDRAWAL_H
 5
 6   #include "Screen.h" // include definition of class Screen              
 7   #include "Keypad.h" // include definition of class Keypad              
 8   #include "CashDispenser.h" // include definition of class CashDispenser
 9   #include "BankDatabase.h" // include definition of class BankDatabase  
10
11   class Withdrawal
12   {
13   private:
14      // attributes
15      int accountNumber; // account to withdraw funds from
16      double amount; // amount to withdraw
17
18      // references to associated objects                                  
19      Screen &screen; // reference to ATM's screen                         
20      Keypad &keypad; // reference to ATM's keypad                         
21      CashDispenser &cashDispenser; // reference to ATM's cash dispenser   
22      BankDatabase &bankDatabase; // reference to the account info database
23   }; // end class Withdrawal
24
25   #endif // WITHDRAWAL_H


Fig. 23.5. Declaring references to objects associated with class Withdrawal.

4. It turns out that including the header files for classes Screen, Keypad, CashDispenser and BankDatabase in Fig. 23.5 does more than is necessary. Class Withdrawal contains references to objects of these classes—it does not contain actual objects—and the amount of information required by the compiler to create a reference differs from that which is required to create an object. Recall that creating an object requires that you provide the compiler with a definition of the class that introduces the name of the class as a new user-defined type and indicates the data members that determine how much memory is required to store the object. Declaring a reference (or pointer) to an object, however, requires only that the compiler knows that the object’s class exists—it does not need to know the size of the object. Any reference (or pointer), regardless of the class of the object to which it refers, contains only the memory address of the actual object. The amount of memory required to store an address is a physical characteristic of the computer’s hardware. The compiler thus knows the size of any reference (or pointer). As a result, including a class’s full header file when declaring only a reference to an object of that class is unnecessary—we need to introduce the name of the class, but we do not need to provide the data layout of the object, because the compiler already knows the size of all references. C++ provides a statement called a forward declaration that signifies that a header file contains references or pointers to a class, but that the class definition lies outside the header file. We can replace the #includes in the Withdrawal class definition of Fig. 23.5 with forward declarations of classes Screen, Keypad, CashDispenser and BankDatabase (lines 6–9 in Fig. 23.6). Rather than #include the entire header file for each of these classes, we place only a forward declaration of each class in the header file for class Withdrawal. If class Withdrawal contained actual objects instead of references (i.e., if the ampersands in lines 19–22 were omitted), then we’d need to #include the full header files.


 1   // Fig. 23.6: Withdrawal.h
 2   // Definition of class Withdrawal that represents a withdrawal transaction
 3   #ifndef WITHDRAWAL_H
 4   #define WITHDRAWAL_H
 5
 6   class Screen; // forward declaration of class Screen              
 7   class Keypad; // forward declaration of class Keypad              
 8   class CashDispenser; // forward declaration of class CashDispenser
 9   class BankDatabase; // forward declaration of class BankDatabase  
10
11   class Withdrawal
12   {
13   private:
14      // attributes
15      int accountNumber; // account to withdraw funds from
16      double amount; // amount to withdraw
17
18      // references to associated objects
19      Screen &screen; // reference to ATM's screen
20      Keypad &keypad; // reference to ATM's keypad
21      CashDispenser &cashDispenser; // reference to ATM's cash dispenser
22      BankDatabase &bankDatabase; // reference to the account info database
23   }; // end class Withdrawal
24
25   #endif // WITHDRAWAL_H


Fig. 23.6. Using forward declarations in place of #include directives.

Using a forward declaration (where possible) instead of including a full header file helps avoid a preprocessor problem called a circular include. This problem occurs when the header file for a class A #includes the header file for a class B and vice versa. Some preprocessors are not be able to resolve such #include directives, causing a compilation error. If class A, for example, uses only a reference to an object of class B, then the #include in class A’s header file can be replaced by a forward declaration of class B to prevent the circular include.

5. Use the operations located in the third compartment of Fig. 23.1 to write the function prototypes of the class’s member functions. If we’ve not yet specified a return type for an operation, we declare the member function with return type void. Refer to the class diagrams of Figs. 6.206.23 to declare any necessary parameters. For example, adding the public operation execute in class Withdrawal, which has an empty parameter list, yields the prototype in line 15 of Fig. 23.7. [Note: We code the definitions of member functions in .cpp files when we implement the complete ATM system in Section 23.4.]


 1   // Fig. 23.7: Withdrawal.h
 2   // Definition of class Withdrawal that represents a withdrawal transaction
 3   #ifndef WITHDRAWAL_H
 4   #define WITHDRAWAL_H
 5
 6   class Screen; // forward declaration of class Screen
 7   class Keypad; // forward declaration of class Keypad
 8   class CashDispenser; // forward declaration of class CashDispenser
 9   class BankDatabase; // forward declaration of class BankDatabase
10
11   class Withdrawal
12   {
13   public:
14      // operations
15      void execute(); // perform the transaction
16   private:
17      // attributes
18      int accountNumber; // account to withdraw funds from
19      double amount; // amount to withdraw
20
21      // references to associated objects
22      Screen &screen; // reference to ATM's screen
23      Keypad &keypad; // reference to ATM's keypad
24      CashDispenser &cashDispenser; // reference to ATM's cash dispenser
25      BankDatabase &bankDatabase; // reference to the account info database
26   }; // end class Withdrawal
27
28   #endif // WITHDRAWAL_H


Fig. 23.7. Adding operations to the Withdrawal class header file.


Image Software Engineering Observation 23.1

Several UML modeling tools can convert UML-based designs into C++ code, considerably speeding the implementation process. For more information on these “automatic” code generators, refer to our UML Resource Center at www.deitel.com/UML/.


This concludes our discussion of the basics of generating class header files from UML diagrams. In Section 23.3, we demonstrate how to modify the header files to incorporate the object-oriented concept of inheritance.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.116.14.118