Class Withdrawal
(Figs. 23.32–23.33) derives from Transaction
and represents a withdrawal ATM transaction. Figure 23.32 expands upon the header file for this class developed in Fig. 23.13. Class Withdrawal
has a constructor and one member function execute
, which we discuss shortly. Recall from the class diagram of Fig. 23.11 that class Withdrawal
has one attribute, amount
, which line 16 implements as an int
data member. Figure 23.10 models associations between class Withdrawal
and classes Keypad
and CashDispenser
, for which lines 17–18 implement references keypad
and cashDispenser
, respectively. Line 19 is the function prototype of a private
utility function that we soon discuss.
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
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 static const 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
Figure 23.33 contains the member-function definitions for class Withdrawal
. Line 3 #include
s the class’s definition, and lines 4–7 #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’ll soon discuss how the class uses this constant.
Class Withdrawal
’s constructor (defined in lines 13–20 of Fig. 23.33) has five parameters. It uses a base-class initializer in line 16 to pass parameters userAccountNumber
, atmScreen
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 23–81) 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 29–30 get references to the bank database and the ATM’s screen by invoking member functions inherited from base class Transaction
.
Lines 33–80 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
). This loop continuously returns 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 85–129). This 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 85–129) 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 in lines 95–126 repeats until userChoice
takes on a value other than 0
. We’ll see shortly that this occurs when the user makes a valid selection from the menu. Lines 98–105 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 in lines 110–125 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
in lines 95–126 terminates and line 128 returns userChoice
. If the user selects the cancel menu option, lines 120–121 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 123–124 display an error message and the user is returned to the withdrawal menu.
The if
statement in line 39 in member function execute
determines whether the user has selected a withdrawal amount or chosen to cancel. If the user cancels, lines 77–78 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 44–45 retrieve the available balance of the current user’s Account
and store it in a local double
variable availableBalance
. Next, the if
statement in line 48 determines whether the selected amount is less than or equal to the user’s available balance. If it isn’t, lines 70–72 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 in 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 64–66 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 56–57 then instruct the cash dispenser to dispense the cash to the user and set cashDispensed
to true
. Finally, lines 60–61 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
.
In the function calls in lines 64–66 and lines 70–72, 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 64–66 execute, displayMessageLine
receives a single string
as a parameter, even though the argument in the function call appears as two string literals.