Defining Class-Wide Members
The data members and member functions currently defined in the CreditCardAccount class are instance members. Each CreditCardAccount instance has its own accountNumber, currentBalance, and creditLimit. Likewise, when you invoke the member functions MakePurchase, MakeRepayment, and PrintStatement, you must specify which CreditCardAccount instance you’re using, as shown in the following figure.
|
C++ also lets you define class-wide members, which pertain to the entire class rather than to a specific instance. For example, you can define a class-wide data member named numberOfAccounts to count how many CreditCardAccount instances have been created. Similarly, you can provide a class-wide member function named GetNumberOfAccounts to retrieve this count, as shown in the following figure.
Let’s see how to define class-wide data members and member functions.
Defining Class-Wide Data Members
To define a class-wide data member, use the static keyword as follows:
class CreditCardAccount
{
private:
// Declare class-wide data member
static int numberOfAccounts;
// ... Other existing members, as before
};
This declaration tells the compiler that there will be a class-wide data member named numberOfAccounts. This statement also allocates permanent storage for the numberOfAccounts variable. This variable will be available for the entire lifetime of the program, even before any CreditCardAccount objects have been created. If you do not initialize numberOfAccounts explicitly, the default initial value is 0. If you forget to define numberOfAccounts altogether, you’ll get a link error when you try to build the program. The link error tells you that numberOfAccounts hasn’t been defined.
In this exercise, you will add a static numberOfAccounts data member to the CreditCardAccount class. You will increment this data member every time a new CreditCardAccount object is created.
1. Continue using the project from the previous exercise.
2. Open CreditCardAccount.h, and declare the static numberOfAccounts data member as follows:
class CreditCardAccount
{
private:
static int numberOfAccounts;
// ... Other existing members, as before
};
3. Open CreditCardAccount.cpp, and define the numberOfAccounts data member as follows:
int CreditCardAccount::numberOfAccounts = 0;
Add this statement after all the #include directives but outside of any function body.
4. Open CreditCardAccount.cpp, and define the numberOfAccounts data member as follows. Modify the CreditCardAccount constructor so that it increments numberOfAccounts every time a new CreditCardAccount object is created.
CreditCardAccount::CreditCardAccount(long number, double limit)
{
accountNumber = number;
creditLimit = limit;
currentBalance = 0.0;
numberOfAccounts++;
Console::Write("Number of accounts created: ");
Console::WriteLine(numberOfAccounts);
}
5. Open CreditOrganizer.cpp. Modify the main() function so that it creates and uses several CreditCardAccount objects.
Console::WriteLine("Creating first object");
CreditCardAccount * account1;
account1 = new CreditCardAccount(12345, 2000);
account1->MakePurchase(300);
account1->PrintStatement();
Console::WriteLine("\nCreating second object");
CreditCardAccount * account2;
account2 = new CreditCardAccount(67890, 5000);
account2->MakePurchase(750);
account2->PrintStatement();
Console::WriteLine("\nDestroying objects");
delete account1;
delete account2;
6. Build the program, and fix any compiler errors.
7. Run the program.
Every time a new CreditCardAccount object is created, the program increments numberOfAccounts and displays its latest value.
Defining Class-Wide Member Functions
To define a class-wide member function, use the static keyword in the function declaration as follows:
class CreditCardAccount
{
public:
static int GetNumberOfAccounts();
// ... Other existing members, as before
};
Implement the function in the source file as follows. Note that you don’t use the static keyword on the implementation, but only on the declaration inside the class definition.
int CreditCardAccount::GetNumberOfAccounts()
{
return numberOfAccounts;
}
A static member function can only access static class members. For example, GetNumberOfAccounts can access numberOfAccounts, but it cannot access accountNumber, currentBalance, or creditLimit. To call a static member function, use the class name rather than a particular instance, as shown in this example:
int n = CreditCardAccount::GetNumberOfAccounts();
The class name emphasizes the fact that CreditCardAccount is a class-wide member function, rather than an instance member function. You have seen the syntax ClassName::FunctionName before. Every time you display a message on the console, you use a statement such as Console::WriteLine("Hello world"). This statement calls the static member function WriteLine on the Console class.
In this exercise, you will define a static GetNumberOfAccounts member function in the CreditCardAccount class. You will then call this function several times in main().
1. Continue using the project from the previous exercise.
2. Open CreditCardAccount.h, and declare the GetNumberOfAccounts function as follows:
class CreditCardAccount
{
public:
static int GetNumberOfAccounts();
// ... Other existing members, as before
};
3. Open CreditCardAccount.cpp, and implement the GetNumberOfAccounts function as follows:
int CreditCardAccount::GetNumberOfAccounts()
{
return numberOfAccounts;
}
4. Open CreditOrganizer.cpp. Modify the main() function so that it calls GetNumberOfAccounts at various stages during execution.
int n = CreditCardAccount::GetNumberOfAccounts();
Console::Write("Number of accounts initially: ");
Console::WriteLine(n);
Console::WriteLine("\nCreating first object");
CreditCardAccount * account1;
account1 = new CreditCardAccount(12345, 2000);
account1->MakePurchase(300);
account1->PrintStatement();
Console::WriteLine("\nCreating second object");
CreditCardAccount * account2;
account2 = new CreditCardAccount(67890, 5000);
account2->MakePurchase(750);
account2->PrintStatement();
n = CreditCardAccount::GetNumberOfAccounts();
Console::Write("\nNumber of accounts now: ");
Console::WriteLine(n);
Console::WriteLine("\nDestroying objects");
delete account1;
delete account2;
5. Build the program, and fix any compiler errors.
6. Run the program. The program displays the messages shown here.
Defining Object Relationships
For the remainder of this module, you will see how to define relationships between objects in a Visual C++ application. Visual C++ applications typically contain many objects. These objects communicate with each other to achieve the overall functionality needed in the application. To illustrate object relationships, you will add a new class named LoyaltyScheme to your credit card application. The LoyaltyScheme class will allow credit card owners to accrue bonus points when they use their credit card. The bonus points act as a reward for the customer’s loyal use of the credit card. When a CreditCardAccount object is first created, it will not have a LoyaltyScheme object. The LoyaltyScheme object will be created when CreditCardAccount reaches 50 percent of its credit limit. Subsequently, every $10 spent using the credit card will accrue one bonus point in the LoyaltyScheme object, as long as the account is above the 50 percent mark. When the CreditCardAccount object is finally destroyed, the LoyaltyScheme object must also be destroyed. The following figure shows the lifetimes of the CreditCardAccount and LoyaltyScheme objects.
To achieve this functionality, you will complete the following exercises:
Define the LoyaltyScheme class.
Implement the LoyaltyScheme class.
Create, use, and destroy LoyaltyScheme objects.
Test the application.
Defining the LoyaltyScheme Class
In this exercise, you will define the LoyaltyScheme class in a new header file named LoyaltyScheme.h.
// LoyaltyScheme.h
class LoyaltyScheme
{
public:
// Constructor
LoyaltyScheme();
// Destructor
~LoyaltyScheme();
// Earn one point per $10 spent
void EarnPointsOnAmount(double amountSpent);
// Redeem points
void RedeemPoints(int points);
// Return the value of totalPoints
int GetPoints();
private:
// Total points accrued so far
int totalPoints;
};
Continue using the project from the previous exercise.
Select the Project menu, and then choose Add New Item. In the Add New Item dialog box, select the template Header File (.h). In the Name field, type LoyaltyScheme.h and click Add.
Type the following code in the header file to define the LoyaltyScheme class:
// LoyaltyScheme.h
class LoyaltyScheme
{
public:
// Constructor
LoyaltyScheme();
// Destructor
~LoyaltyScheme();
// Earn one point per $10 spent
void EarnPointsOnAmount(double amountSpent);
// Redeem points
void RedeemPoints(int points);
// Return the value of totalPoints
int GetPoints();
private:
// Total points accrued so far
int totalPoints;
};
Build the program, and fix any compiler errors.