Overriding Member Functions

When you define a base class, you must consider whether derived classes will need to override any of your base-class member functions. For each member function in the base class, there are three possibilities:

  • override the member function with customized behavior. The Credit and Debit member functions in BankAccount fit this scenario. These functions simply add or subtract money from the balance—derived classes do not need to override these member functions. Here’s an example:

    __gc __abstract class BankAccount { public: void Credit(double amount); // This function cannot be // overridden void Debit(double amount); // Neither can this one ... };
  • The base-class function performs some task, but derived classes might need to override the function to provide customized behavior. To enable a base-class function to be overridden, you must declare the function using the virtual keyword in the base-class definition, as shown in this example:

    __gc __abstract class BankAccount { public: virtual String * ToString(); // This function can be // overridden ... }; 
  • The base-class function specifies some operation that is required by all derived classes, but each derived class needs to perform the operation in a significantly different way. There is no sensible common behavior you can define in the base class. To achieve this effect, declare the base-class member function using the virtual keyword. At the end of the function prototype, use the syntax = 0, as shown in the following code. This syntax indicates that the function isn’t implemented in the base class—derived classes must override this function. Here’s an example:

    __gc __abstract class BankAccount { public: virtual bool CanDebit(double amount) = 0; // This // function // must be // overridden ... };


In C++, we use the term pure virtual function to describe a function that must be overridden by derived classes. Other programming languages use different terminology and keywords. For example, C# allows you to use the abstract keyword for such a method. Microsoft Visual Basic uses the MustOverride keyword.

In this exercise, you will define a ToString member function in the BankAccount class. You will declare this function as virtual to give derived classes the opportunity to override the function if they want to.

You will also define a pure virtual function named CanDebit in the BankAccount class. This forces all derived classes to implement the CanDebit function.

  1. Continue using the project from the previous exercise.

  2. Open BankAccount.h, and add the following public function declarations to the BankAccount class:

    virtual String * ToString(); // Derived classes // can override virtual bool CanDebit(double amount) = 0; // Derived classes // must override

  3. Open BankAccount.cpp, and implement the ToString function as follows:

    String * BankAccount::ToString() { String * result = new String(S"Account holder: "); result = String::Concat(result, accountHolder); result = String::Concat(result, S", Balance: "); result = String::Concat(result, balance.ToString()); return result; } 
  4. Modify the Debit member function as follows:

    void BankAccount::Debit(double amount) { if (CanDebit(amount)) { balance -= amount; Console::Write(S"Debit succeeded, new balance is: "); Console::WriteLine(balance); } else { Console::Write(S"Debit refused, balance is still: "); Console::WriteLine(balance); } }

    Notice that Debit now calls CanDebit to verify that the debit is allowed. CanDebit isn’t implemented in BankAccount, but all derived classes are obliged to provide this function. At run time, the correct version of CanDebit will be called depending on the type of bank account being used for the debit operation—polymorphism in action!

  5. Open CurrentAccount.h, and add the following public function declarations to the CurrentAccount class:

    virtual String * ToString(); // Choose to // override ToString virtual bool CanDebit(double amount); // Obliged to // override CanDebit
  6. Open CurrentAccount.cpp, and implement the ToString function as follows:

    String * CurrentAccount::ToString() { String * result = __super::ToString(); result = String::Concat(result, S", Overdraft Limit: "); result = String::Concat(result, overdraftLimit.ToString()); return result; }

    The __super::ToString() syntax calls the ToString function in the superclass (BankAccount). This call returns a string containing the account holder’s name and balance. We concatenate the overdraftLimit value to this string and return it.

  7. Still in CurrentAccount.cpp, implement the CanDebit function as follows:

    bool CurrentAccount::CanDebit(double amount) { if (amount <= balance + overdraftLimit) { return true; } else { return false; } }
  8. Open SavingsAccount.h, and add the following public function declaration to the SavingsAccount class:

    virtual bool CanDebit(double amount); // Obliged to // override CanDebit

    You are obliged to override CanDebit because it’s a pure virtual function. However, you do not have to override ToString because the base class (BankAccount) provides a default implementation of this function. The SavingsAccount class chooses not to override ToString.

  9. Open SavingsAccount.cpp, and implement the CanDebit function as follows:

    bool SavingsAccount::CanDebit(double amount) { if (amount <= balance / 10) { return true; } else { return false; } }

    This function enables the user to withdraw one-tenth of the current balance.

  10. Open BigBank.cpp, and replace the existing code in the _tmain function with the following:

    Console::WriteLine(S"Testing the CurrentAccount"); CurrentAccount * current = new CurrentAccount(S"Emily", 100); current->Credit(500); current->Debit(600); // Should be accepted current->Debit(1); // Should be declined Console::WriteLine(current->ToString()); Console::WriteLine(S"\nTesting the SavingsAccount"); SavingsAccount * savings = new SavingsAccount(S"Thomas"); savings->Credit(500); savings->Debit(50); // Should be accepted savings->Debit(46); // Should be declined Console::WriteLine(savings->ToString()); return 0;
  11. Build and run the program. The program displays output shown in the following figure on the console.

    click to expand

  12. Create a breakpoint on the first statement in the _tmain function, and start the program in the debugger. Step through the program one statement at a time, stepping into each function to see which version is called during execution.

Microsoft Visual C++  .NET(c) Step by Step
Microsoft Visual C++ .NET(c) Step by Step
ISBN: 735615675
Year: 2003
Pages: 208

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net