Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
his bonus chapter walks you through a series of programs related to a fictional bank account. The first program, BUDGET1, solves the bank account problem using simplistic and error-prone functional programming techniques. BUDGET2 cleans things up by bundling account information into one of two classes, Savings or Checking. BUDGET3 expresses the relationship between Savings and Checking by extending them from a common Account class. BUDGET3 also stores its objects in a linked list. BUDGET4 generalizes the linked list by turning it into the template class LinkedList<class T>, and BUDGET5 uses one of the Standard Template Library containers instead of reinventing the wheel.
BUDGET1
The chapters that make up Parts I and II provide you the programming information necessary to write your own non-trivial programs. The following program, BUDGET1, is just such a program. This program uses the C++ concepts presented in Parts I and II of the book. The BUDGET program is a simple bank account register program. Heres what it does: Gives the user the ability to create one or more bank accounts. Assigns an account number to each account.
BC2
BC3
BC4
BC5
200 to terminate:c
to terminate:x
Heres how the BUDGET1.C program works. Two arrays are created, one to contain account numbers and the other their balances. These two arrays are kept in synch; that is, balance[n] contains the balance of the account accountNumber[n] no matter what the value of n. Due to the limitations of a fixed-length array, the program can accommodate only MAXACCOUNTS number of bank accounts. The main program is divided into two sections: the accumulation section, where the deposits and withdrawals are accumulated into accounts; and the display section. The accumulation section first enters a loop in which the
BC6
Coding styles
You may notice that I try to be consistent in my indentation and in my naming of variables. We humans have a limited amount of CPU power between our ears. We need to direct our CPU power toward getting programs working, not toward figuring out simple stuff like indentation. This makes it important that you be consistent in how you name variables, where you place open and close braces, and so on. This is called your coding style. When you have developed a style, stick to it after a while, your coding style will become second nature. Youll find that you can code your programs in less time and read your programs with less effort. When working on a project with several programmers, its just as important that you all use the same style to avoid a Tower of Babel effect with conflicting and confusing formats. The programmer editor can help here both Visual C++ and Dev-C++ allow you to set up certain programming style parameters such as the number of spaces to indent, whether the braces are lined up with the for statement or are indented as well, and so on. In addition, I strongly suggest that you enable every error and warning message that your compiler can produce. Even if you decide that a particular warning is not a problem, why would you want it suppressed? You can always ignore it. More often than not, even a warning represents a potential problem or programming style that needs to be corrected. Some people dont like the compiler finding their slip-ups because they think its embarrassing and they think that correcting things to get rid of the warnings wastes time. Just think how embarrassing and time-consuming it is to painstakingly search for a bug only to find that its a problem your compiler told you about hours ago.
BC7
BUDGET2
The BUDGET2 program converts the function-based BUDGET1 solution to an object-based solution based on active classes. Youll need to be familiar with the concepts I present through Part III to understand BUDGET2. The budget problem is to set up accounts like those you see in a bank. These simple accounts provide for deposits (thats good) and withdrawals (thats even better). (The earlier version of BUDGET introduced at the end of Part II of the book handle only a single type of bank account.) This version handles two types of accounts each with its own, slightly different rules. Checking accounts: Charge a fee of 20 cents per check if the balance drops below $500. Do not charge a fee when the balance is above $500.
BC8
bers protected, so a few access functions are necessary in case a nonmember function needs the account number or balance. Like all classes, Checking and Savings need a constructor to initialize objects to legal values (mostly to a balance of 0). Two additional member functions are also necessary: deposit() and withdrawal(). Finally, I added one other member function called display() to display the current object. This is not a requirement, but it is common to let the object display itself rather than rely on an external function to do so. (Those other functions would need knowledge of the classs internals in order to know how to display it properly, and thats something you want to avoid.) Here is the resulting program:
// // BUDGET2.CPP - BUDGET program with active Savings and // Checking classes. // #include <cstdio> #include <cstdlib> #include <iostream> using namespace std; // the maximum number of accounts one can have const int MAXACCOUNTS = 10; // Checking - this describes checking accounts class Checking { public: Checking(int initializeAN = 0) : accountNumber(initializeAN), balance(0.0) {} // access functions int accountNo() { return accountNumber; } double acntBalance() { return balance; } // transaction functions void deposit(double amount) { balance += amount;
BC9
BC10
BC11
BC12
// wait until user is ready before terminating program // to allow the user to see the program results system(PAUSE); return 0; }
BC13
BC14
exit:s
exit:c
exit:C
exit:x
Starting with class Checking, you can see each of the member functions mentioned earlier. The constructor assigns the account number. The = 0 allows the program to construct an object with a default account number of 0:
BC15
In this case, the Checking object c1 is created with account number 123, and the object c2 is created with the default account number of 0. The functions accountNo() and acntBalance() give the outside world access to the protected members accountNumber and balance. The point of such a function is to allow non-class functions to read these values but not modify them. In addition, these access functions will shield outside functions from any future changes in the way that the account number or the balance is stored. The deposit() and withdrawal() functions either deposit or withdraw an amount. Because the deposit() function is simple, it is defined directly inline within the class. The withdrawal() function, being a bit more complicated, is declared here but defined later. The display() function outputs the important data members to the standard output. Notice that providing a function with a display() method is a common (and good) programming practice. The class Savings is virtually identical to the class Checking except for the addition of the member noWithdrawals, which is used to track the number of withdrawals made. Room for the savings account and checking account objects is allocated in the arrays svgAcnts and chkAcnts, respectively. The maximum number of accounts is MAXACCOUNTS. The main() function is slightly more complicated than its BUDGET1 cousin because it must deal with two different types of accounts. After the check for X, main() uses the switch construct to decide between C checking and S savings accounts. The switch construct is used here because it is easier to extend by adding more cases, and because it provides a default case to handle erroneous input. Just as before, the second section of main() actually displays the account data accumulated in the initial section. Notice how the internals of the Checking and Savings objects are hidden from main(). For example, main() asks the objects to display themselves (meaning display the internal components) main() has no idea how the classes choose to do this, nor does it care.
BC16
BUDGET3
BUDGET3 continues the metamorphosis of the purely functional BUDGET1 through the object-based version BUDGET2 into an object-oriented program. This program uses the concepts presented through Part IV of the book. The BUDGET programs handle bank deposits and withdrawals for a simulated bank. The user enters a series of bank accounts followed by the deposits and withdrawals for that account. After the user has entered all her transactions, the program displays the balances for each account plus the overall balance. BUDGET2 and BUDGET3 simulate both Checking and Savings accounts. Checking accounts charge a small fee for withdrawals when the balance is less than $500, and savings accounts charge a large fee after the first withdrawal irrespective of the balance. BUDGET2 was an improvement over BUDGET1 in one sense: It isolated the details of account classes from the exterior functions that manipulate accounts. Unfortunately, BUDGET2 contained a large amount of redundancy between the two classes (Savings and Checking); redundancies that you can avoid using the inheritance principles. BUDGET3 adds the following improvements. With the help of the new superhero inheritance and its sidekick polymorphism, you can rationalize the two
BC17
BC18
The following AccountLinkedList.cpp file implements a simple linked list of bank accounts (this class is far from a complete implementation):
// AccountLinkedList - maintain a linked list of Account // objects #include AccountLinkedList.h
BC19
A Node object is assigned to each Account. Each Node::pNext pointer points to the next Account in the list. The AccountLinkedList object represents the entire list. AccountLinkedList::pHead points to the first Node in the list of Account objects. For simplicity, the addNode() member function adds Node objects to the beginning of the list.
BC20
BC21
BC22
BC23
BC24
The first class contained in BUDGET3 is Account. This class encapsulates all the things you know about generic accounts: They are identified by account numbers. Each account carries a balance. Users can make deposits or withdrawals from a bank account. This one class implements the source code that was common between the
Savings and Checking account classes in the BUDGET2 program at the end of Part III. Savings and Checking are now subclasses of Account. I have made Account::type() purely virtual so that it can be overridden appropriately
in the two subclasses. The Account constructor initializes the unique account information by saving off the account number and the initial balance, which is assumed to be zero if
BC25
BC26
BC27
I placed both the AccountLinkedList and Node objects in the Lists namespace to separate them from the Account class. The AccountLinkedList class simply contains the head pointer of the linked list of Node objects. The head pointer is the pointer to the first node in a list. The meat is really in the Node class. Each Node object points to its neighbor through its pNext member. In addition, the node points to an Account object. The pointer pAccount simply refers back to the linked list object itself so that the object knows what linked list it belongs to. Look again at the BUDGET3.cpp source file. main() defined an AccountLinkedList class object this is the linked list. A reference to this list is passed to the constructor for Account. The constructor for Node() that is invoked from the Account constructor creates a node thats a member of the specified linked list and that points to an account. The vestigial AccountLinkedList.cpp source file is present to allow the AccountLinkedList class to reference a method within Node. This definition cannot be placed in the class because Node is defined in the include file after
BC28
BUDGET4
The BUDGET programs handle bank deposits and withdrawals for a simulated bank. The user enters a series of bank accounts followed by the deposits and withdrawals for that account. After the user has entered all her transactions, the program displays the balances for each account plus the overall balance. BUDGET2 and BUDGET3 simulate both Checking and Savings accounts. Checking accounts charge a small fee for withdrawals when the balance is less than $500, and savings accounts charge a large fee after the first withdrawal
BC29
BC30
BC31
BC32
BC33
BC34
BC35
BC36
The first three lines before the definition of the class Account instantiate the template classes LinkedList and Node into the classes LinkedList<Node> and Node<Account>, respectively. These three lines create the classes necessary to link up Account objects into a linked list.
BC37
BUDGET5
This BUDGET5 program is the last in a long, proud line of programs that all solve the same basic problem: maintaining a list of savings and checking accounts. (Each BUDGET program did the job a little better than its predecessor.) The BUDGET3 program evolved the Account, Savings, and Checking classes about as far as they could go using object-oriented concepts as inheritance. In addition, BUDGET3 maintained its Account objects in a linked list. Unfortunately, this version of the program included an AccountLinkedList class that was dedicated to containing accounts. BUDGET4 released the shackles of Account-itude using the template class LinkedList<class T>.
BC38
Listing containers
The Standard Template Library (STL) defines a number of different container types that can be used to maintain a group of objects. The simplest list container is the aptly named list. The following version of BUDGET uses the list template class:
// BUDGET5.CPP - Identical to other BUDGET programs except // for the use of an STL list container to // hold budget objects (rather than a fixed // array or a home made linked list) #include <cstdio> #include <cstdlib> #include <iostream> #include <list> using namespace std; // Account - this abstract class incorporates properties // common to both account types: Checking and // Savings. However, its missing the concept // withdrawal(), which is different between the two class Account { public: Account::Account(unsigned accNo) { // initialize the data members of the object accountNumber = accNo; balance = 0; count++; } // access functions int accountNo() { return accountNumber; } double acntBalance() { return balance; } static int noAccounts() { return count; }
BC39
BC40
BC41
BC42
BC43
The include file list contains the definition of the STL list template class (thats logical enough). The Account, Checking, and Savings classes are unchanged from their BUDGET3 and BUDGET4 siblings. The real changes start with the definition of AccountPtr about halfway through the program.
pointer to account.
main() passes the list of pointers to Account objects to getAccounts() and to displayResults(). The getAccounts() method adds Account objects to the end of the list by invoking the method push_back().
The displayResults() could remove Account objects from the list by using one of the pop methods; however, that would be whats known as a destructive
BC44
moves the iterator to the next object in the list. The remainder of the BUDGET5 program is the same as BUDGET4 and BUDGET3 that precede it.