Class Withdrawal (Figs. G.19G.20) derives from TRansaction and represents a withdrawal ATM transaction. Figure G.19 expands upon the header file for this class developed in Fig. 13.31. Class Withdrawal has a constructor and one member function execute, which we discuss shortly. Recall from the class diagram of Fig. 13.29 that class Withdrawal has one attribute, amount, which line 16 implements as an int data member. Figure 13.28 models associations between class Withdrawal and classes Keypad and CashDispenser, for which lines 1718 implement references keypad and cashDispenser, respectively. Line 19 is the function prototype of a private utility function that we soon discuss.
Figure G.19. Withdrawal class definition.
(This item is displayed on page 1308 in the print version)
1 // Withdrawal.h 2 // Withdrawal class definition. Represents a withdrawal transaction. 3 #ifndef WITHDRAWAL_H 4 #define WITHDRAWAL_H 5 6 #include "Transaction.h" // Transaction class definition 7 class Keypad; // forward declaration of class Keypad 8 class CashDispenser; // forward declaration of class CashDispenser 9 10 class Withdrawal : public Transaction 11 { 12 public: 13 Withdrawal( int, Screen &, BankDatabase &, Keypad &, CashDispenser & ); 14 virtual void execute(); // perform the transaction 15 private: 16 int amount; // amount to withdraw 17 Keypad &keypad; // reference to ATM's keypad 18 CashDispenser &cashDispenser; // reference to ATM's cash dispenser 19 int displayMenuOfAmounts() const; // display the withdrawal menu 20 }; // end class Withdrawal 21 22 #endif // WITHDRAWAL_H |
Figure G.20. Withdrawal class member-function definitions.
(This item is displayed on pages 1309 - 1311 in the print version)
1 // Withdrawal.cpp 2 // Member-function definitions for class Withdrawal. 3 #include "Withdrawal.h" // Withdrawal class definition 4 #include "Screen.h" // Screen class definition 5 #include "BankDatabase.h" // BankDatabase class definition 6 #include "Keypad.h" // Keypad class definition 7 #include "CashDispenser.h" // CashDispenser class definition 8 9 // global constant that corresponds to menu option to cancel 10 const static int CANCELED = 6; 11 12 // Withdrawal constructor initialize class's data members 13 Withdrawal::Withdrawal( int userAccountNumber, Screen &atmScreen, 14 BankDatabase &atmBankDatabase, Keypad &atmKeypad, 15 CashDispenser &atmCashDispenser ) 16 : Transaction( userAccountNumber, atmScreen, atmBankDatabase ), 17 keypad( atmKeypad ), cashDispenser( atmCashDispenser ) 18 { 19 // empty body 20 } // end Withdrawal constructor 21 22 // perform transaction; overrides Transaction's pure virtual function 23 void Withdrawal::execute() 24 { 25 bool cashDispensed = false; // cash was not dispensed yet 26 bool transactionCanceled = false; // transaction was not canceled yet 27 28 // get references to bank database and screen 29 BankDatabase &bankDatabase = getBankDatabase(); 30 Screen &screen = getScreen(); 31 32 // loop until cash is dispensed or the user cancels 33 do 34 { 35 // obtain the chosen withdrawal amount from the user 36 int selection = displayMenuOfAmounts(); 37 38 // check whether user chose a withdrawal amount or canceled 39 if ( selection != CANCELED ) 40 { 41 amount = selection; // set amount to the selected dollar amount 42 43 // get available balance of account involved 44 double availableBalance = 45 bankDatabase.getAvailableBalance( getAccountNumber() ); 46 47 // check whether the user has enough money in the account 48 if ( amount <= availableBalance ) 49 { 50 // check whether the cash dispenser has enough money 51 if ( cashDispenser.isSufficientCashAvailable( amount ) ) 52 { 53 // update the account involved to reflect withdrawal 54 bankDatabase.debit( getAccountNumber(), amount ); 55 56 cashDispenser.dispenseCash( amount ); // dispense cash 57 cashDispensed = true; // cash was dispensed 58 59 // instruct user to take cash 60 screen.displayMessageLine( 61 " Please take your cash from the cash dispenser." ); 62 } // end if 63 else // cash dispenser does not have enough cash 64 screen.displayMessageLine( 65 " Insufficient cash available in the ATM." 66 " Please choose a smaller amount." ); 67 } // end if 68 else // not enough money available in user's account 69 { 70 screen.displayMessageLine( 71 " Insufficient funds in your account." 72 " Please choose a smaller amount." ); 73 } // end else 74 } // end if 75 else // user chose cancel menu option 76 { 77 screen.displayMessageLine( " Canceling transaction..." ); 78 transactionCanceled = true; // user canceled the transaction 79 } // end else 80 } while ( !cashDispensed && !transactionCanceled ); // end do...while 81 } // end function execute 82 83 // display a menu of withdrawal amounts and the option to cancel; 84 // return the chosen amount or 0 if the user chooses to cancel 85 int Withdrawal::displayMenuOfAmounts() const 86 { 87 int userChoice = 0; // local variable to store return value 88 89 Screen &screen = getScreen(); // get screen reference 90 91 // array of amounts to correspond to menu numbers 92 int amounts[] = { 0, 20, 40, 60, 100, 200 }; 93 94 // loop while no valid choice has been made 95 while ( userChoice == 0 ) 96 { 97 // display the menu 98 screen.displayMessageLine( " Withdrawal options:" ); 99 screen.displayMessageLine( "1 - $20" ); 100 screen.displayMessageLine( "2 - $40" ); 101 screen.displayMessageLine( "3 - $60" ); 102 screen.displayMessageLine( "4 - $100" ); 103 screen.displayMessageLine( "5 - $200" ); 104 screen.displayMessageLine( "6 - Cancel transaction" ); 105 screen.displayMessage( " Choose a withdrawal option (1-6): " ); 106 107 int input = keypad.getInput(); // get user input through keypad 108 109 // determine how to proceed based on the input value 110 switch ( input ) 111 { 112 case 1: // if the user chose a withdrawal amount 113 case 2: // (i.e., chose option 1, 2, 3, 4 or 5), return the 114 case 3: // corresponding amount from amounts array 115 case 4: 116 case 5: 117 userChoice = amounts[ input ]; // save user's choice 118 break; 119 case CANCELED: // the user chose to cancel 120 userChoice = CANCELED; // save user's choice 121 break; 122 default: // the user did not enter a value from 1-6 123 screen.displayMessageLine( 124 " Ivalid selection. Try again." ); 125 } // end switch 126 } // end while 127 128 return userChoice; // return withdrawal amount or CANCELED 129 } // end function displayMenuOfAmounts |
Withdrawal Class Member-Function Definitions
Figure G.20 contains the member-function definitions for class Withdrawal. Line 3 #includes the class's definition, and lines 47 #include the definitions of the other classes used in Withdrawal's member functions. Line 11 declares a global constant corresponding to the cancel option on the withdrawal menu. We will soon discuss how the class uses this constant.
Class Withdrawal's constructor (defined in lines 1320 of Fig. G.20) has five parameters. It uses a base-class initializer in line 16 to pass parameters userAccountNumber, atm-Screen and atmBankDatabase to base class transaction's constructor to set the data members that Withdrawal inherits from TRansaction. The constructor also takes references atmKeypad and atmCashDispenser as parameters and assigns them to reference data members keypad and cashDispenser using member initializers (line 17).
Class Withdrawal overrides transaction's pure virtual function execute with a concrete implementation (lines 2381) that performs the steps involved in a withdrawal. Line 25 declares and initializes a local bool variable cashDispensed. This variable indicates whether cash has been dispensed (i.e., whether the transaction has completed successfully) and is initially false. Line 26 declares and initializes to false a bool variable transactionCanceled that indicates whether the transaction has been canceled by the user. Lines 2930 get references to the bank database and the ATM's screen by invoking member functions inherited from base class transaction.
Lines 3380 contain a do...while statement that executes its body until cash is dispensed (i.e., until cashDispensed becomes true) or until the user chooses to cancel (i.e., until transactionCanceled becomes true). We use this loop to continuously return the user to the start of the transaction if an error occurs (i.e., the requested withdrawal amount is greater than the user's available balance or greater than the amount of cash in the cash dispenser). Line 36 displays a menu of withdrawal amounts and obtains a user selection by calling private utility function displayMenuOfAmounts (defined in lines 85129). This member function displays the menu of amounts and returns either an int withdrawal amount or the int constant CANCELED to indicate that the user has chosen to cancel the transaction.
Member function displayMenuOfAmounts (lines 85129) first declares local variable userChoice (initially 0) to store the value that the member function will return (line 87). Line 89 gets a reference to the screen by calling member function getScreen inherited from base class transaction. Line 92 declares an integer array of withdrawal amounts that correspond to the amounts displayed in the withdrawal menu. We ignore the first element in the array (index 0) because the menu has no option 0. The while statement at lines 95126 repeats until userChoice takes on a value other than 0. We will see shortly that this occurs when the user makes a valid selection from the menu. Lines 98105 display the withdrawal menu on the screen and prompt the user to enter a choice. Line 107 obtains integer input through the keypad. The switch statement at lines 110125 determines how to proceed based on the user's input. If the user selects a number between 1 and 5, line 117 sets userChoice to the value of the element in amounts at index input. For example, if the user enters 3 to withdraw $60, line 117 sets userChoice to the value of amounts[ 3 ] (i.e., 60). Line 118 terminates the switch. Variable userChoice no longer equals 0, so the while at lines 95126 terminates and line 128 returns userChoice. If the user selects the cancel menu option, lines 120121 execute, setting userChoice to CANCELED and causing the member function to return this value. If the user does not enter a valid menu selection, lines 123124 display an error message and the user is returned to the withdrawal menu.
The if statement at line 39 in member function execute determines whether the user has selected a withdrawal amount or chosen to cancel. If the user cancels, lines 7778 execute to display an appropriate message to the user and set transactionCanceled to true. This causes the loop-continuation test in line 80 to fail and control to return to the calling member function (i.e., ATM member function performTransactions). If the user has chosen a withdrawal amount, line 41 assigns local variable selection to data member amount. Lines 4445 retrieve the available balance of the current user's Account and store it in a local double variable availableBalance. Next, the if statement at line 48 determines whether the selected amount is less than or equal to the user's available balance. If it is not, lines 7072 display an appropriate error message. Control then continues to the end of the do...while, and the loop repeats because both cashDispensed and transactionCanceled are still false. If the user's balance is high enough, the if statement at line 51 determines whether the cash dispenser has enough money to satisfy the withdrawal request by invoking the cashDispenser's isSufficientCashAvailable member function. If this member function returns false, lines 6466 display an appropriate error message and the do...while repeats. If sufficient cash is available, then the requirements for the withdrawal are satisfied, and line 54 debits amount from the user's account in the database. Lines 5657 then instruct the cash dispenser to dispense the cash to the user and set cashDispensed to TRue. Finally, lines 6061 display a message to the user that cash has been dispensed. Because cashDispensed is now TRue, control continues after the do...while. No additional statements appear below the loop, so the member function returns control to class ATM.
Notice that, in the function calls in lines 6466 and lines 7072, we divide the argument to Screen member function displayMessageLine into two string literals, each placed on a separate line in the program. We do so because each argument is too long to fit on a single line. C++ concatenates (i.e., combines) string literals adjacent to each other, even if they are on separate lines. For example, if you write "Happy ""Birthday" in a program, C++ will view these two adjacent string literals as the single string literal "Happy Birthday". As a result, when lines 6466 execute, displayMessageLine receives a single string as a parameter, even though the argument in the function call appears as two string literals.
Introduction to Computers, the Internet and World Wide Web
Introduction to C++ Programming
Introduction to Classes and Objects
Control Statements: Part 1
Control Statements: Part 2
Functions and an Introduction to Recursion
Arrays and Vectors
Pointers and Pointer-Based Strings
Classes: A Deeper Look, Part 1
Classes: A Deeper Look, Part 2
Operator Overloading; String and Array Objects
Object-Oriented Programming: Inheritance
Object-Oriented Programming: Polymorphism
Templates
Stream Input/Output
Exception Handling
File Processing
Class string and String Stream Processing
Web Programming
Searching and Sorting
Data Structures
Bits, Characters, C-Strings and structs
Standard Template Library (STL)
Other Topics
Appendix A. Operator Precedence and Associativity Chart
Appendix B. ASCII Character Set
Appendix C. Fundamental Types
Appendix D. Number Systems
Appendix E. C Legacy Code Topics
Appendix F. Preprocessor
Appendix G. ATM Case Study Code
Appendix H. UML 2: Additional Diagram Types
Appendix I. C++ Internet and Web Resources
Appendix J. Introduction to XHTML
Appendix K. XHTML Special Characters
Appendix L. Using the Visual Studio .NET Debugger
Appendix M. Using the GNU C++ Debugger
Bibliography