1 实验目的
(1)学习为什么要使用虚函数;
(2)学习如何声明函数为虚函数;
(3)学习如何声明异类数组(基类指针分别指向不同的派生类对象);(4)学习如何使用虚函数和异类数组实现多态调用。
2 实验内容
2.1 程序模拟银行帐户管理
(1)问题描述创建一个银行账户的继承层次,表示银行的所有客户账户。所有的客户都能在他们的银行账户存钱,取钱,并且账户还可以分成更具体的类型。
例如,存款账户SavingsAccount依靠存款生利,支票账户CheckingAccount会对每笔交易(即存款或取款)收取费用。
创建一个类层次,以Account作为基类,SavingsAccount和CheckingAccount作为派生类。
基类Account应该包括一个double类型的数据成员balance,表示账户的余额。该类应当提供三个成员函数。成员函数credit可以向当前余额加钱;成员函数debit负责从账户中取钱,并且保证账户不会被透支。如果提取金额大于账户金额,函数将保持balance不变,并打印信息“Debit amount exceeded account balance”;成员函数getBalance则返回当前balance的值。
派生类SavingsAccount不仅继承了基类Account的功能,而且应提供一个附加的double类型数据成员interestRate表示这个账户的比率(百分比)。SavingsAccount的构造函数应接受初始余额值和初始利率值,还应提供一个public成员函数calculateInterest,返回代表账户的利息的一个double值,这个值是balance和interestRate的乘积。类SavingsAccount应继承成员函数credit和debit,不需要重新定义。
派生类CheckingAccount不仅继承基类Account的功能,还提供一个附加的double类型数据成员表示每笔交易的费用。CheckingAccount的构造函数应接受初始余额值和交易费用值。类CheckingAccount需要重新定义成员函数credit和debit,当每笔交易完成时,从balance中减去每笔交易的费用。重新定义这些函数时应分别使用基类Account的相关函数来执行账户余额的更新。CheckingAccount的debit函数只有当钱被成功提取时(即提取金额不超过账户余额时)才应收取交易费。
提示:定义Account的debit函数使它返回一个bool类型值,表示钱是否被成功提取。然后利用该值决定是否需要扣除交易费。如果取款或存款后,账户的余额小于每笔交易的费用,则废弃这次交易,使账户余额恢复到取款或存款之前的值,并打印“Transaction fee exceeded account balance while debiting”或“Transaction fee exceeded account balance while crediting”。(2)问题要求要求将每个类的定义和实现分开在不同的文件里,并严格按照上述名称定义成员变量和成员函数,所有类的成员变量均定义为private的。当这个继承层次中的类定义完毕后,编写一个主程序,能够多态地调用不同账户的成员函数。
main.cpp
int main()
{
Account *accounts[3];
accounts[0] = new SavingsAccount(100, 3); //余额100元,利息3%accounts[1] = new CheckingAccount(100, 5); //余额100元,交易费5元accounts[2] = new CheckingAccount(50, 5); //余额50元,交易费5元
for (int i = 0; i < 3; i++)
{
cout << "第" << i + 1 << "次循环的结果:" << endl;
accounts[i]->debit(200); //借款200元
accounts[i]->debit(40);
accounts[i]->credit(50); //存款50元
accounts[i]->debit(49);
accounts[i]->debit(43);
accounts[i]->credit(1);
//将Account指针强制转换为SavingAccount指针
SavingsAccount *derivedPtr =dynamic_cast<SavingsAccount*>(accounts[i]);
if(derivedPtr != NULL) //如果类型兼容,转换成功
derivedPtr->credit(derivedPtr->calculateInterest());
cout << fixed << setprecision(2); //使用定点数格式,2位小数部分
cout << "账户的余额为:" << accounts[i]->getBalance() << endl;
}
}
account.h
#pragma once
class Account
{
public:
Account(double balance);
virtual bool credit(double deposit);
virtual bool debit(double withdraw);
double getBalance();
private:
double balance;
};
CheckingAccount.h
#pragma once
#include "account.h"
class CheckingAccount :public Account
{
public:
CheckingAccount(double balance, double fee);
bool debit(double withdraw);
bool credit(double deposit);
private:
double fee;
};
SavingsAccount.h
#pragma once
#include "account.h"
class SavingsAccount :public Account
{
public:
SavingsAccount(double balance, double interestRate);
double calculateInterest();
private:
double interestRate;
};
account.cpp
#include "account.h"
#include <iostream>
#include <cmath>
using namespace std;
Account::Account(double balance)
:balance(balance)
{
}
bool Account::credit(double deposit)
{
balance += deposit;
return true;
}
bool Account::debit(double withdraw)
{
if (withdraw > balance)
{
cout << "Debit amount exceeded account balance" << endl;
return false;
}
else
{
balance -= withdraw;
return true;
}
}
double Account::getBalance()
{
return balance;
}
CheckingAccount.cpp
#include "CheckingAccount.h"
#include <iostream>
using namespace std;
CheckingAccount::CheckingAccount(double balance, double fee)
:Account(balance),fee(fee)
{
}
bool CheckingAccount::debit(double withdraw)
{
if (Account::debit(withdraw))
{
if (getBalance() < fee)
{
cout << "Transaction fee exceeded account balance while debiting" << endl;
Account::credit(withdraw);
return false;
}
else
{
Account::debit(fee);
return true;
}
}
}
bool CheckingAccount::credit(double deposit)
{
if (Account::credit(deposit))
{
if (getBalance() < fee)
{
cout << "Transaction fee exceeded account balance while crediting" << endl;
Account::debit(deposit);
return false;
}
else
{
Account::debit(fee);
return true;
}
}
}
SavingsAccount.cpp
#include "SavingsAccount.h"
SavingsAccount::SavingsAccount(double balance, double interestRate)
:Account(balance),interestRate(interestRate)
{
}
double SavingsAccount::calculateInterest()
{
return interestRate * getBalance()/100.0;
}