Class BankDatabase
(Figs. 23.26–23.27) models the bank’s database with which the ATM interacts to access and modify a user’s account information. The class definition (Fig. 23.26) declares function prototypes for the class’s constructor and several member functions. We discuss these momentarily. The class definition also declares the BankDatabase
’s data members. We determine one data member for class BankDatabase
based on its composition relationship with class Account
. Recall from Fig. 23.10 that a BankDatabase
is composed of zero or more objects of class Account
. Line 24 of Fig. 23.26 implements data member accounts
—a vector
of Account
objects—to implement this composition relationship. Lines 6–7 allow us to use vector
in this file. Line 27 contains the function prototype for a private
utility function getAccount
that allows the member functions of the class to obtain a pointer to a specific Account
in the accounts vector
.
1 // BankDatabase.h
2 // BankDatabase class definition. Represents the bank's database.
3 #ifndef BANK_DATABASE_H
4 #define BANK_DATABASE_H
5
6 #include <vector> // class uses vector to store Account objects
7 using namespace std;
8
9 #include "Account.h" // Account class definition
10
11 class BankDatabase
12 {
13 public:
14 BankDatabase(); // constructor initializes accounts
15
16 // determine whether account number and PIN match those of an Account
17 bool authenticateUser( int, int ); // returns true if Account authentic
18
19 double getAvailableBalance( int ); // get an available balance
20 double getTotalBalance( int ); // get an Account's total balance
21 void credit( int, double ); // add amount to Account balance
22 void debit( int, double ); // subtract amount from Account balance
23 private:
24 vector< Account > accounts; // vector of the bank's Accounts
25
26 // private utility function
27 Account * getAccount( int ); // get pointer to Account object
28 }; // end class BankDatabase
29
30 #endif // BANK_DATABASE_H
1 // BankDatabase.cpp
2 // Member-function definitions for class BankDatabase.
3 #include "BankDatabase.h" // BankDatabase class definition
4
5 // BankDatabase default constructor initializes accounts
6 BankDatabase::BankDatabase()
7 {
8 // create two Account objects for testing
9 Account account1( 12345, 54321, 1000.0, 1200.0 );
10 Account account2( 98765, 56789, 200.0, 200.0 );
11
12 // add the Account objects to the vector accounts
13 accounts.push_back( account1 ); // add account1 to end of vector
14 accounts.push_back( account2 ); // add account2 to end of vector
15 } // end BankDatabase default constructor
16
17 // retrieve Account object containing specified account number
18 Account * BankDatabase::getAccount( int accountNumber )
19 {
20 // loop through accounts searching for matching account number
21 for ( size_t i = 0; i < accounts.size(); i++ )
22 {
23 // return current account if match found
24 if ( accounts[ i ].getAccountNumber() == accountNumber )
25 return &accounts[ i ];
26 } // end for
27
28 return NULL; // if no matching account was found, return NULL
29 } // end function getAccount
30
31 // determine whether user-specified account number and PIN match
32 // those of an account in the database
33 bool BankDatabase::authenticateUser( int userAccountNumber,
34 int userPIN )
35 {
36 // attempt to retrieve the account with the account number
37 Account * const userAccountPtr = getAccount( userAccountNumber );
38
39 // if account exists, return result of Account function validatePIN
40 if ( userAccountPtr != NULL )
41 return userAccountPtr->validatePIN( userPIN );
42 else
43 return false; // account number not found, so return false
44 } // end function authenticateUser
45
46 // return available balance of Account with specified account number
47 double BankDatabase::getAvailableBalance( int userAccountNumber )
48 {
49 Account * const userAccountPtr = getAccount( userAccountNumber );
50 return userAccountPtr->getAvailableBalance();
51 } // end function getAvailableBalance
52
53 // return total balance of Account with specified account number
54 double BankDatabase::getTotalBalance( int userAccountNumber )
55 {
56 Account * const userAccountPtr = getAccount( userAccountNumber );
57 return userAccountPtr->getTotalBalance();
58 } // end function getTotalBalance
59
60 // credit an amount to Account with specified account number
61 void BankDatabase::credit( int userAccountNumber, double amount )
62 {
63 Account * const userAccountPtr = getAccount( userAccountNumber );
64 userAccountPtr->credit( amount );
65 } // end function credit
66
67 // debit an amount from Account with specified account number
68 void BankDatabase::debit( int userAccountNumber, double amount )
69 {
70 Account * const userAccountPtr = getAccount( userAccountNumber );
71 userAccountPtr->debit( amount );
72 } // end function debit
Figure 23.27 contains the member-function definitions for class BankDatabase
. We implement the class with a default constructor (lines 6–15) that adds Account
objects to data member accounts
. For the sake of testing the system, we create two new Account
objects with test data (lines 9–10), then add them to the end of the vector
(lines 13–14). The Account
constructor has four parameters—the account number, the PIN assigned to the account, the initial available balance and the initial total balance.
Recall that class BankDatabase
serves as an intermediary between class ATM
and the actual Account
objects that contain users’ account information. Thus, the member functions of class BankDatabase
do nothing more than invoke the corresponding member functions of the Account
object belonging to the current ATM user.
We include private utility function getAccount
(lines 18–29) to allow the BankDatabase
to obtain a pointer to a particular Account
within vector accounts
. To locate the user’s Account
, the BankDatabase
compares the value returned by member function getAccountNumber
for each element of accounts
to a specified account number until it finds a match. Lines 21–26 traverse the accounts vector
. If the account number of the current Account
(i.e., accounts[ i ]
) equals the value of parameter accountNumber
, the member function immediately returns the address of the current Account
(i.e., a pointer to the current Account
). If no account has the given account number, then line 28 returns NULL
. Note that this member function must return a pointer, as opposed to a reference, because there is the possibility that the return value could be NULL
—a reference cannot be NULL, but a pointer can.
Note that vector
function size
(invoked in the loop-continuation condition in line 21) returns the number of elements in a vector
as a value of type size_t
(which is usually unsigned int
). As a result, we declare the control variable i
to be of type size_t
, too. On some compilers, declaring i
as an int
would cause the compiler to issue a warning message, because the loop-continuation condition would compare a signed
value (i.e., an int
) and an unsigned
value (i.e., a value of type size_t
).
Member function authenticateUser
(lines 33–44) proves or disproves the an ATM user’s identity. This function takes a user-specified account number and user-specified PIN as arguments and indicates whether they match the account number and PIN of an Account
in the database. Line 37 calls utility function getAccount
, which returns either a pointer to an Account
with userAccountNumber
as its account number or NULL
to indicate that userAccountNumber
is invalid. We declare userAccountPtr
to be a const
pointer because, once the member function aims this pointer at the user’s Account
, the pointer should not change. If getAccount
returns a pointer to an Account
object, line 41 returns the bool
value returned by that object’s validatePIN
member function. BankDatabase
’s authenticateUser
member function does not perform the PIN comparison itself—rather, it forwards userPIN
to the Account
object’s validatePIN
member function to do so. The value returned by Account
member function validatePIN
indicates whether the user-specified PIN matches the PIN of the user’s Account
, so member function authenticateUser
simply returns this value to the client of the class (i.e., ATM
).
BankDatabase
trusts the ATM
to invoke member function authenticateUser
and receive a return value of true
before allowing the user to perform transactions. BankDatabase
also trusts that each Transaction
object created by the ATM
contains the valid account number of the current authenticated user and that this is the account number passed to the remaining BankDatabase
member functions as argument userAccountNumber
. Member functions getAvailableBalance
(lines 47–51), getTotalBalance
(lines 54–58), credit
(lines 61–65) and debit
(lines 68–72) therefore simply retrieve a pointer to the user’s Account
object with utility function getAccount
, then use this pointer to invoke the appropriate Account
member function on the user’s Account
object. We know that the calls to getAccount
within these member functions will never return NULL
, because userAccountNumber
must refer to an existing Account
. Note that getAvailableBalance
and getTotalBalance
return the values returned by the corresponding Account
member functions. Also, credit
and debit
simply redirect parameter amount
to the Account
member functions they invoke.