Account
Class with a Balance; Data ValidationWe 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.
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
.
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.
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.
deposit
Member Function with ValidationMember 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.
getBalance
Member FunctionMember 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.
Account
Objects with BalancesThe 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.
Account
Objects’ Initial BalancesWhen 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.
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.
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 name
s 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 name
s and balance
s of both Account
s again to show that only account2
’s balance
has changed.
main
FunctionThe 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
.
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.
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
.
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
.