Implementing the LoyaltyScheme Class
In this exercise, you will implement the LoyaltyScheme class in a new source file named LoyaltyScheme.cpp
|
Add two #include statements at the start of the file, as shown here:
#include "stdafx.h"
#include "LoyaltyScheme.h"
Add the following code to expose the System namespace:
using namespace System;
Implement the LoyaltyScheme constructor and destructor as follows:
LoyaltyScheme::LoyaltyScheme()
{
Console::WriteLine("Congratulations, you now qualify for bonus points");
totalPoints = 0;
}
LoyaltyScheme::~LoyaltyScheme(void)
{
Console::WriteLine("Loyalty scheme now closed");
}
Implement the EarnPointsOnAmount member function as follows:
void LoyaltyScheme::EarnPointsOnAmount(double amountSpent)
{
int points = (int)(amountSpent/10);
totalPoints += points;
Console::Write("New bonus points earned: ");
Console::WriteLine(points);
}
The syntax (int)(amountSpent/10) divides the amount spent by 10 and converts the value to an int data type.
Implement the RedeemPoints member function as follows:
void LoyaltyScheme::RedeemPoints(int points)
{
if (points <= totalPoints)
{
totalPoints -= points;
}
else
{
totalPoints = 0;
}
}
This function enables the user to redeem some or all of the accrued bonus points.
Implement the GetPoints member function as follows:
int LoyaltyScheme::GetPoints()
{
return totalPoints;
}
A complete code is shown below.
// LoyaltyScheme.cpp
#include "stdafx.h"
#include "LoyaltyScheme.h"
using namespace System;
LoyaltyScheme::LoyaltyScheme()
{
Console::WriteLine("Congratulations, you now qualify for bonus points");
totalPoints = 0;
}
LoyaltyScheme::~LoyaltyScheme(void)
{
Console::WriteLine("Loyalty scheme now closed");
}
void LoyaltyScheme::EarnPointsOnAmount(double amountSpent)
{
int points = (int)(amountSpent/10);
totalPoints += points;
Console::Write("New bonus points earned: ");
Console::WriteLine(points);
}
void LoyaltyScheme::RedeemPoints(int points)
{
if (points <= totalPoints)
{
totalPoints -= points;
}
else
{
totalPoints = 0;
}
}
int LoyaltyScheme::GetPoints()
{
return totalPoints;
}
Build the program, and fix any compiler errors.
Creating, Using, and Destroying LoyaltyScheme Objects
In this exercise, you will extend the CreditCardAccount class to support the loyalty scheme functionality.
1. Continue using the project from the previous exercise.
2. Open CreditCardAccount.h. At the start of the file, add a #include directive as follows:
#include "LoyaltyScheme.h"
This will enable you to use the LoyaltyScheme class in this header file.
3. Add a private data member to the CreditCardAccount class, as follows:
// Pointer to a LoyaltyScheme object
LoyaltyScheme * ptrLoyaltyScheme;
This pointer defines an association between a CreditCardAccount object and a LoyaltyScheme object.
4. Add a public member function to the CreditCardAccount class as follows:
void RedeemLoyaltyPoints();
This function acts as a wrapper to the RedeemPoints function in the LoyaltyScheme class. When you want to redeem loyalty points, you call RedeemLoyaltyPoints on your CreditCardAccount object. This function will call RedeemPoints on the underlying LoyaltyScheme object to do the work. Relying on a member’s existing functionality is an example of delegation. The CreditCardAccount object delegates the RedeemPoints operation to the LoyaltyScheme object.
5. Open CreditCardAccount.cpp, and find the CreditCardAccount constructor. Add the following statement in the constructor body:
ptrLoyaltyScheme = 0;
This statement sets the ptrLoyaltyScheme pointer to 0 initially. Zero is a special value for a pointer because it indicates that the pointer doesn’t point to a real object yet. The LoyaltyScheme object won’t be created until the credit card balance reaches 50 percent of the credit limit.
6. Modify the MakePurchase function as follows to accrue bonus points when the credit card balance reaches 50 percent of the credit limit:
bool CreditCardAccount::MakePurchase(double amount)
{
if (currentBalance + amount > creditLimit)
{ return false; }
else
{
currentBalance += amount;
// If current balance is 50% (or more) of credit limit...
if (currentBalance >= creditLimit / 2)
{
// If LoyaltyScheme object doesn’t exist yet...
if (ptrLoyaltyScheme == 0)
{
// Create it
ptrLoyaltyScheme = new LoyaltyScheme();
}
else
{
// LoyaltyScheme already exists, so accrue bonus points
ptrLoyaltyScheme->EarnPointsOnAmount(amount);
}
}
return true;
}
}
7. Implement the RedeemLoyaltyPoints function as follows. RedeemLoyaltyPoints is a new member function that enables the user to redeem some or all of the loyalty points in the associated LoyaltyScheme object.
void CreditCardAccount::RedeemLoyaltyPoints()
{
// If the LoyaltyScheme object doesn’t exist yet...
if (ptrLoyaltyScheme == 0)
{
// Display an error message
Console::WriteLine("Sorry, you do not have a loyalty scheme yet");
}
else
{
// Tell the user how many points are currently available
Console::Write("Points available: ");
Console::WriteLine(ptrLoyaltyScheme->GetPoints());
// Ask the user how many points they want to redeem
Console::WriteLine("How many points do you want to redeem? ");
String ^ input = Console::ReadLine();
int points = System::Convert::ToInt32(input);
// Redeem the points
ptrLoyaltyScheme->RedeemPoints(points);
// Tell the user how many points are left
Console::Write("Points remaining: ");
Console::WriteLine(ptrLoyaltyScheme->GetPoints());
}
}
It’s important to test the ptrLoyaltyScheme pointer before you use it. If you forget to test the pointer and the pointer is still 0, your program will cause a null pointer exception at run time. This is a very common error in C++ applications.
8. Add the following statement to the CreditCardAccount destructor:
delete ptrLoyaltyScheme;
This statement deletes the LoyaltyScheme object because it’s no longer needed. When you use delete, you do not need to test for a null pointer. The delete operator has an internal null pointer test.
9. Build the program, and fix any compiler errors.
Testing the Application
In this exercise, you will modify the code in CreditOrganizer.cpp to test the loyalty scheme functionality.
1. Continue using the project from the previous exercise.
2. Open CreditOrganizer.cpp. Modify the main() function as follows:
Console::WriteLine("Creating account object");
CreditCardAccount * account1;
account1 = new CreditCardAccount(12345, 2000);
Console::WriteLine("\nMaking a purchase (300)");
account1->MakePurchase(300);
Console::WriteLine("\nMaking a purchase (700)");
account1->MakePurchase(700);
Console::WriteLine("\nMaking a purchase (500)");
account1->MakePurchase(500);
Console::WriteLine("\nRedeeming points");
account1->RedeemLoyaltyPoints();
Console::WriteLine("\nDeleting account object");
delete account1;
3. Build the program, and fix any compiler errors.
4. Run the program. The program creates a CreditCardAccount object and makes various purchases. Once the credit card balance reaches $1,000, a LoyaltyScheme object is created. Subsequent purchases accrue a loyalty point for every $10 spent.
When you try to redeem loyalty points, the program tells you how many points are available and asks how many you want to redeem. Enter a value such as 35. The program tells you how many points are left. At the end of the program, the CreditCardAccount object is deleted. The associated LoyaltyScheme object is deleted at the same time. The following figure shows the messages displayed on the console during the program.
Quick Reference For This Module
To | Do this |
Define a class. | Add a header file to your project. Define the class in the header file. For example:
class MyClass { public: void MyFunction(); private: int myData; };
|
Implement a class. | Add a source file to your project. In the source file, use a #include statement to include the header file that contains the class definition. Then implement the member functions in the source file. For example:
#include "MyHeader.h"
void MyClass::MyFunction() { myData = myData * 2; }
|
Provide a constructor in a class. | Declare the constructor in the header file, and implement it in the source file. The constructor must have the same name as the class and cannot return a value. However, a constructor can take parameters. For example:
// Header file class MyClass { public: MyClass(int n); // ... };
// Source file MyClass::MyClass(int n) { myData = n; }
|
Provide a destructor in a class. | Declare the destructor in the header file, and implement it in the source file. The destructor must have the same name as the class, preceded by a tilde (~). The destructor cannot return a value or take any parameters. For example:
// Header file class MyClass { public: ~MyClass(); // ... }; // Source file MyClass::~MyClass() { Console::WriteLine("Goodbye"); }
|
Create and destroy objects of an unmanaged class. | Create an object using the new keyword, passing parameters into the constructor if necessary. Delete the object using the delete keyword. For example:
MyClass * ptrToObject; ptrToObject = new myClass(100); ptrToObject->MyFunction(); delete ptrToObject;
|
Define class-wide data members. | Declare the data member using the static keyword. Define the data member in the source file. For example:
// Header file class MyClass { private: static int myClassData; // ... };
// Source file int MyClass:myClassData = 0;
|
Define and use class-wide member functions. | Declare the member function using the static keyword. Implement the member function in the source file. Call the function using the syntax ClassName::FunctionName. For example:
// Header file class MyClass { public: static void MyClassFunction(); // ... };
// Source file void MyClass::MyClassFunction() { myClassData++; }
// Client code MyClass::MyClassFunction();
|
Define relationships between objects. | Define all the required classes, and use pointers to denote relationships between objects. For example, if an instance of class A needs to point to an instance of class B, use the following:
class B { // ... };
class A { // ... private: B * pointerToB; };
|
Table 1 |