3.6 Account Class with a Balance; Data Validation

We now define an Account class that maintains a bank account’s balance in addition to the name. In Chapter 2 we used the data type int to represent integers. For simplicity, we’ll use data type int to represent the account balance. In Chapter 4, you’ll see how to represent numbers with decimal points.

3.6.1 Data Member balance

A typical bank services many accounts, each with its own balance. In this updated Account class (Fig. 3.8), line 42


int balance{0}; // data member with default initial value

declares a data member balance of type int and initializes its value to 0. This is known as an in-class initializer and was introduced in C++11. Every object of class Account contains its own copies of both the name and the balance.

Fig. 3.8 Account class with name and balance data members, and a constructor and deposit function that each perform validation.

Alternate View

 1   // Fig. 3.8: Account.h
 2   // Account class with name and balance data members, and a
 3   // constructor and deposit function that each perform validation.
 4   #include <string>
 5
 6   class Account {
 7   public:
 8      // Account constructor with two parameters
 9      Account(std::string accountName, int initialBalance)
10         : name{accountName} { // assign accountName to data member name
11
12         // validate that the initialBalance is greater than 0; if not,
13         // data member balance keeps its default initial value of 0
14         if (initialBalance > 0) { // if the initialBalance is valid     
15            balance = initialBalance; // assign it to data member balance
16         }                                                               
17      }
18
19      // function that deposits (adds) only a valid amount to the balance
20      void deposit(int depositAmount) {                                  
21         if (depositAmount > 0) { // if the depositAmount is valid       
22            balance = balance + depositAmount; // add it to the balance  
23         }                                                               
24      }                                                                  
25
26      // function returns the account balance
27      int getBalance() const {               
28         return balance;                     
29      }                                      
30
31      // function that sets the name
32      void setName(std::string accountName) {
33         name = accountName;
34      }
35
36      // function that returns the name
37      std::string getName() const {
38         return name;
39      }
40   private:
41      std::string name; // account name data member
42      int balance{0}; // data member with default initial value
43   }; // end class Account

Account’s Member Functions Can All Use balance

The statements in lines 15, 22 and 28 use the variable balance even though it was not declared in any of the member functions. We can use balance in these member functions because it’s a data member in the same class definition.

3.6.2 Two-Parameter Constructor with Validation

The class has a constructor and four member functions. It’s common for someone opening an account to deposit money immediately, so the constructor (lines 9–17) now receives a second parameter— initialBalance of type int that represents the starting balance. We did not declare this constructor explicit (as in Fig. 3.4), because this constructor has more than one parameter.

Lines 14–16 of Fig. 3.8


if (initialBalance > 0) { // if the initialBalance is valid
   balance = initialBalance; // assign it to data member balance
}

ensure that data member balance is assigned parameter initialBalance’s value only if that value is greater than 0 —this is known as validation or validity checking. If so, line 15 assigns initialBalance’s value to data member balance. Otherwise, balance remains at 0—its default initial value that was set at line 42 in class Account’s definition.

3.6.3 deposit Member Function with Validation

Member function deposit (lines 20–24) does not return any data when it completes its task, so its return type is void. The member function receives one int parameter named depositAmount. Lines 21–23


if (depositAmount > 0) { // if the depositAmount is valid
   balance = balance + depositAmount; // add it to the balance
}

ensure that parameter depositAmount’s value is added to the balance only if the parameter value is valid (i.e., greater than zero)—another example of validity checking. Line 22 first adds the current balance and depositAmount, forming a temporary sum which is then assigned to balance, replacing its prior value (recall that addition has a higher precedence than assignment). It’s important to understand that the calculation


balance + depositAmount

on the right side of the assignment operator in line 22 does not modify the balance—that’s why the assignment is necessary. Section 4.12 shows a more concise way to write line 22.

3.6.4 getBalance Member Function

Member function getBalance (lines 27–29) allows the class’s clients to obtain the value of a particular Account object’s balance. The member function specifies return type int and an empty parameter list. Like member function getName, getBalance is declared const, because in the process of returning the balance the function does not, and should not, modify the Account object on which it’s called.

3.6.5 Manipulating Account Objects with Balances

The main function in Fig. 3.9 creates two Account objects (lines 10–11) and attempts to initialize them with a valid balance of 50 and an invalid balance of -7, respectively—for the purpose of our examples, we assume that balances must be greater than or equal to zero. Lines 14–17 output the account names and balances, which are obtained by calling each Account’s getName and getBalance member functions.

Fig. 3.9 Displaying and updating Account balances.

Alternate View

 1   // Fig. 3.9: AccountTest.cpp
 2   // Displaying and updating Account balances.
 3   #include <iostream>
 4   #include  "Account.h"
 5
 6   using namespace std;
 7
 8   int main()
 9   {
10      Account account1{"Jane Green", 50};
11      Account account2{"John Blue", -7}; 
12
13      // display initial balance of each object
14      cout << "account1: " << account1.getName() << " balance is $"
15         << account1.getBalance();
16      cout << "
account2: " << account2.getName() << " balance is $"
17         << account2.getBalance();
18
19      cout << "

Enter deposit amount for account1: "; // prompt
20      int depositAmount;
21      cin >> depositAmount; // obtain user input
22      cout << "adding " << depositAmount << " to account1 balance";
23      account1.deposit(depositAmount); // add to account1’s balance
24
25      // display balances
26      cout << "

account1: " << account1.getName() << " balance is $"
27         << account1.getBalance();
28      cout << "
account2: " << account2.getName() << " balance is $"
29         << account2.getBalance();
30
31      cout << "

Enter deposit amount for account2: "; // prompt
32      cin >> depositAmount; // obtain user input
33      cout << "adding " << depositAmount << " to account2 balance";
34      account2.deposit(depositAmount); // add to account2 balance  
35
36      // display balances
37      cout << "

account1: " << account1.getName() << " balance is $"
38         << account1.getBalance();
39      cout << "
account2: " << account2.getName() << " balance is $"
40         << account2.getBalance() << endl;
41   }

account1: Jane Green balance is $50
account2: John Blue balance is $0

Enter deposit amount for account1: 25
adding 25 to account1 balance

account1: Jane Green balance is $75
account2: John Blue balance is $0

Enter deposit amount for account2: 123
adding 123 to account2 balance

account1: Jane Green balance is $75
account2: John Blue balance is $123

Displaying the Account Objects’ Initial Balances

When member function getBalance is called for account1 from line 15, the value of account1’s balance is returned from line 28 of Fig. 3.8 and displayed by the output statement in lines 14–15 (Fig. 3.9). Similarly, when member function getBalance is called for account2 from line 17, the value of the account2’s balance is returned from line 28 of Fig. 3.8 and displayed by the output statement (Fig. 3.9, lines 16–17). The balance of account2 is initially 0, because the constructor rejected the attempt to start account2 with a negative balance, so the data member balance retains its default initial value.

Reading a Deposit Amount from the User and Making a Deposit

Line 19 prompts the user to enter a deposit amount for account1. Line 20 declares local variable depositAmount to store each deposit amount entered by the user. We did not initialize depositAmount, because as you’ll learn momentarily, variable depositAmount’s value will be input by the user’s input.

Error-Prevention Tip 3.3

Most C++ compilers issue a warning if you attempt to use the value of an uninitialized variable. This helps you avoid dangerous execution-time logic errors. It’s always better to get the warnings and errors out of your programs at compilation time rather than execution time.

Line 21 reads the deposit amount from the user and places the value into local variable depositAmount. Line 22 displays the deposit amount. Line 23 calls object account1’s deposit member function with the depositAmount as the member function’s argument. When the member function is called, the argument’s value is assigned to the parameter depositAmount of member function deposit (line 20 of Fig. 3.8); then member function deposit adds that value to the balance. Lines 26–29 (Fig. 3.9) output the names and balance s of both Account s again to show that only account1’s balance has changed.

Line 31 prompts the user to enter a deposit amount for account2. Line 32 obtains the input from the user. Line 33 displays the depositAmount. Line 34 calls object account2’s deposit member function with depositAmount as the member function’s argument ; then member function deposit adds that value to the balance. Finally, lines 37–40 output the names and balance s of both Account s again to show that only account2’s balance has changed.

Duplicated Code in the main Function

The six statements at lines 14–15, 16–17, 26–27, 28–29, 37–38 and 39–40 are almost identical. Each outputs an Account’s name and balance, and differs only in the Account object’s name— account1 or account2. Duplicate code like this can create code maintenance problems when that code needs to be updated. For example, if six copies of the same code all have the same error to fix or the same update to be made, you must make that change six times, without making errors. Exercise 3.13 asks you to modify Fig. 3.9 to include function displayAccount that takes as a parameter an Account object and outputs the object’s name and balance. You’ll then replace main’s duplicated statements with six calls to displayAccount.

Software Engineering Observation 3.4

Replacing duplicated code with calls to a function that contains only one copy of that code can reduce the size of your program and improve its maintainability.

3.6.6 Account UML Class Diagram with a Balance and Member Functions deposit and getBalance

The UML class diagram in Fig. 3.10 concisely models class Account of Fig. 3.8. The diagram models in its second compartment the private attributes name of type string and balance of type int.

Fig. 3.10 UML class diagram for the Account class of Fig. 3.8.

Class Account’s constructor is modeled in the third compartment with parameters accountName of type string and initialBalance of type int. The class’s four public member functions also are modeled in the third compartment—operation deposit with a depositAmount parameter of type int, operation getBalance with a return type of int, operation setName with an accountName parameter of type string and operation getName with a return type of string.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset