/*------------- atm_oopt.cc: ATM machine with tracing ---------------- ATM machine (object-oriented implementation). This version has been modified to trace constuctors. Illustrates object-oriented approach, with classes representing accounts and transactions, derived classes representing subtypes of accounts & transactions, protected members and assertions to preserve meaning (semantics). This file implements the classes declared in atm_oop.h. Programmer: Glenn D. Blank For chapter 14 of "The Universal Machine" Copyright (C) WCB/McGraw-Hill, 1998 --------------------------------------------------------------------*/ #include #include //#include "atm_oop.h" /*----------------------- atm_oop.h: ATM machine ---------------------- ATM machine (object-oriented implementation). Illustrates object-oriented approach, with classes representing accounts and transactions, derived classes representing subtypes of accounts & transactions, protected members and assertions to preserve meaning (semantics). This is the header file declaring classes which are implemented in atm_oop.cc and atm_oopt.cc (with tracing). Programmer: Glenn D. Blank For chapter 14 of "The Universal Machine" Copyright (C) WCB/McGraw-Hill, 1998 ---------------------------------------------------------------------*/ //Account generalizes checking, savings, etc. class Account { public: int getPIN() const; //extract PIN void setPIN(int PIN); //insert PIN //PIN must have four digits float getBalance() const; //extract balance void setBalance(float); //insert balance //balance must be non-negative float addToDeposits(float); //today's deposits float getDeposits(); //extract deposits float subFromBalance(float); //withdraw from balance bool sufficientBalance(float); //can cover amount? const Lstring& getType(); //extract accountType void setType(Lstring); //insert accountType private: int PIN; //Personal Identification Number float balance; //not including today's deposits float deposits; //today's deposits protected: Lstring accountType; //"checking", "savings"... Account(); //default constructor called by derived classes }; //For ATM, Checking and Savings add very little to Account // ... constructors just add Lstring accountType class Checking : public Account { public: Checking(int PIN,float balance); Checking(); //default constructor }; class Savings : public Account { public: Savings(int PIN,float balance); Savings(); //default constructor }; //Transaction generalizes Deposits, Withdrawals, etc. class Transaction { public: float getAmount() const; //extract amount void setAmount(float); //insert amount void askForAmount(); //ask user for amount protected: float amount; //amount of transaction }; //Deposit manages a deposit to any account class Deposit : public Transaction { public: Deposit(Account&); //get amount and add to account deposits }; //Withdrawal manages a withdrawal from any account class Withdrawal : public Transaction { public: Withdrawal(Account&); //get amount and subtract from balance }; //Card ask for user for card and verifies PIN class Card { public: void askForCard(); //prompt user for card bool validPin(int,Account); //user's PIN == account's? }; //ATM class runs the machine class ATM { public: ATM(); //construct a user's accounts bool verifyCard(Card card); //verify PIN on card char chooseTransaction(); //Deposit, Withdraw or Quit char chooseAccount(); //Checking or Savings void runTransaction(char transChoice,char accountChoice); void goodbye(); private: Checking checking; //current user's checking Savings savings; //current user's savings }; #include #include //Member function definitions follow (was atm_oopt.cc) int Account :: getPIN() const //extract PIN { return PIN; } void Account :: setPIN(int pin) //insert PIN { assert(pin >= 1000 && pin <= 9999); //PIN must be 4 digits PIN = pin; } float Account :: getBalance() const //extract balance { return balance; } void Account :: setBalance(float bal) //insert balance { assert(bal >= 0); //no negative balance balance = bal; } float Account :: addToDeposits(float dep) //today's deposits { deposits = deposits + dep; } float Account :: getDeposits() //extract deposits { return deposits; return deposits; } float Account :: subFromBalance(float withdraw) { assert(balance > withdraw); balance = balance - withdraw; return balance; } bool Account :: sufficientBalance(float amount) //Enough in account to cover subtraction of amount? { return (balance >= amount); } const Lstring& Account :: getType() //extract accountType { return accountType; } void Account :: setType(Lstring type) //insert accountType { accountType = type; } //Constructor is protected; only call derived class constructors Account :: Account () //default constructor { cout << "In constructor for base class Account." << endl; deposits = 0; //today's balance start off zero } //For ATM, Checking and Savings add very little to Account // ... constructors just add Lstring accountType Checking :: Checking(int PIN,float balance) { cout << "In constructor for Checking. PIN=" << PIN << " balance=" << balance << endl; setPIN(PIN); setBalance(balance); setType("checking"); } Checking :: Checking() { cout << "In default constructor for Checking." << endl; } //default Savings :: Savings(int PIN,float balance) { cout << "In constructor for Savings. PIN=" << PIN << " balance=" << balance << endl; setPIN(PIN); setBalance(balance); Account::setType("savings"); } Savings :: Savings() { cout << "In default constructor for Savings." << endl; } //default //Transaction generalizes Deposits, Withdrawals, etc. float Transaction :: getAmount() const //extract amount { return amount; } void Transaction :: setAmount(float a) //insert amount { amount = a; } void Transaction :: askForAmount() //ask user for amount { cout << " amount (ddd.cc):$"; float userAmount; //from user cin >> userAmount; if (userAmount < 0) { cout << "Ignoring negative amount.\n"; setAmount(0); } else setAmount(userAmount); } //Deposit manages a deposit to any account Deposit :: Deposit(Account & account) //ask for amount and add to account's deposits { cout << "Deposit"; Transaction :: askForAmount(); //base class's function account.addToDeposits(amount); //add transaction amount cout << "New balance in " << account.getType() << " is $" << account.getBalance() + account.getDeposits() << endl; }; //Withdrawal manages a withdrawal from any account Withdrawal :: Withdrawal(Account & account) //ask for amount and subtract from account's balance { bool dispensed=false; //keep trying until money dispensed while (!dispensed) { cout << "Withdraw"; Transaction :: askForAmount(); //base class's function //can only dispense money in $20 bills if (amount != int(amount) || (int(amount) % 20)) cout << "Sorry, can only dispense money in $20 bills.\n"; else if (!account.sufficientBalance(amount)) //enough to cover? cout << "Sorry, insufficient balance in your " << account.getType() << " account.\n"; else //subtract from balance, dispense & show new balance { account.subFromBalance(amount); //subtract from balance cout << "Dispensing $" << amount << " from " << account.getType() << endl << "New balance in " << account.getType() << " is $" << account.getBalance() + account.getDeposits() << endl; dispensed = true; //exit while loop } //else } //while } //Card asks for user for card and verifies PIN void Card :: askForCard() //prompt user for card { cout << "Welcome to First Virtual Bank's Automatic Teller!\n" << "Please insert your ATM card.\n"; } bool Card :: validPin(int PIN,Account a) //verify user's PIN with account's PIN { return (PIN == a.getPIN()); } //ATM class runs the machine ATM :: ATM() //construct a user's accounts { cout << "In constructor for ATM. Creating accounts...." << endl; checking = Checking(2468,1000.00); //start with $1000 balance savings = Savings(2468,200.00); //start with $200 balance } bool ATM :: verifyCard(Card card) { card.askForCard(); //verify PIN on card int i=0; //give user 3 changes to get PIN right int PIN=0; //from user while (!card.validPin(PIN,checking) && i < 3) { cout << "Please enter 4-digit PIN:"; cin >> PIN; i=i+1; } return card.validPin(PIN,checking); } char ATM :: chooseTransaction() //Deposit, Withdraw or Quit { char choice='?'; //from user while (choice != 'D' && choice != 'W' && choice != 'Q') { cout << "Select Deposit, Withdraw or Quit (d or w or q):"; cin >> choice; choice = toupper(choice); //user can enter lower or upper case } return choice; } char ATM :: chooseAccount() //Checking or Savings or Quit { char choice='?'; //from user while (choice != 'C' && choice != 'S' && choice != 'Q') { cout << "Select Checking, Savings or Quit (c or s or q):"; cin >> choice; choice = toupper(choice); //user can enter lower or upper case } return choice; } void ATM :: runTransaction(char transChoice, char accChoice) { if (transChoice == 'D' && accChoice == 'C') { Deposit d(checking); } //make Deposit to checking else if (transChoice == 'D' && accChoice == 'S') { Deposit d(savings); } //make Deposit to savings else if (transChoice == 'W' && accChoice == 'C') { Withdrawal w(checking); } //make Withdrawal from checking else if (transChoice == 'W' && accChoice == 'S') { Withdrawal w(savings); } //make Deposit to checking } void ATM :: goodbye() { //return card and say good-bye cout << "Please take your ATM card now." << endl; cout << "Thanks for using First Virtual Bank's ATM!" << endl; cout << "Enter a number to quit:"; int in; cin >> in; //wait for input } void main() { ATM atm; //Start up ATM with checking & savings accounts Card card; if (atm.verifyCard(card)) //read and verify a card { char transChoice = atm.chooseTransaction(); while (transChoice != 'Q') { char accChoice = atm.chooseAccount(); if (accChoice != 'Q') atm.runTransaction(transChoice,accChoice); transChoice = atm.chooseTransaction(); } } atm.goodbye(); }