1.程序代码
// brass.h
#ifndef BRASS_H_
#define BRASS_H_
#include<string>
class Brass{
private:
std::string fullName; // 姓名
long acctNum; // 账户号
double balance; // 余额
public:
Brass(const std::string & s = "Nullbody", long an = -1,double bal = 0.0);
void Deposit(double amt);
virtual void Withdraw(double amt);
double Balance() const;
virtual void ViewAcct() const;
virtual ~Brass(){}
};
class BrassPlus : public Brass{
private:
double maxLoan;// 透支额度
double rate; // 透支额度收取的利率
double owesBank; // 欠银行的钱
public:
BrassPlus(const std::string & s = "Nullbody",long an = -1,double bal = 0.0,double ml = 500.0,double r = 0.11125);
BrassPlus(const Brass & ba,double ml = 500,double r = 0.11125);
virtual void ViewAcct() const;
virtual void Withdraw(double amt);
void resetMax(double m){maxLoan = m;}
void resetRate(double r){rate = r;}
void ResetOwes(){owesBank = 0;}
};
#endif
// brass.cpp
#include<iostream>
#include"brass.h"
using std::cout;
using std::endl;
using std::string;
typedef std::ios_base::fmtflags format;
typedef std::streamsize precis;
void restore(format f,precis);
format setFormat();
Brass::Brass(const string & s,long an,double bal):fullName(s),acctNum(an),balance(bal){
}
void Brass::Deposit(double atm){
if(atm < 0){
cout << "Negative deposit not allowed; " << "deposit is cancelled.\n";
}else{
balance += atm;
}
}
void Brass::Withdraw(double amt){
format initialState = setFormat();
precis prec = cout.precision(2);
if(amt < 0){
cout << "Withdrawal amount must be positive;" << "withdrawal canceled.\n";
}else if( amt <= balance){
balance -= amt;
}else{
cout << "Withdrawal amount of $" << amt << " exceeds your banlace.\n" << "Withdrawal canceled.\n";
}
restore(initialState,prec);
}
double Brass::Balance() const{
return balance;
}
void Brass::ViewAcct() const{
format initialState = setFormat();
precis prec = cout.precision(2);
cout << "Client: " << fullName << endl;
cout << "Account Number: " << acctNum << endl;
cout << "Balance : $" << balance << endl;
restore(initialState,prec);
}
BrassPlus::BrassPlus(const string & s,long an,double bal,double ml,double r):Brass(s,an,bal){
maxLoan = ml;
owesBank = 0.0;
rate = r;
}
BrassPlus::BrassPlus(const Brass & ba,double ml,double r):Brass(ba){
maxLoan = ml;
owesBank = 0.0;
rate = r;
}
void BrassPlus::ViewAcct()const{
format initialState = setFormat();
precis prec = cout.precision(2);
Brass::ViewAcct();
cout << "Maximum loan: $" << maxLoan << endl;
cout << "Owed to bank: $" << owesBank << endl;
cout.precision(3);
cout << "Loan Rate: " << 100 * rate << "% \n";
restore(initialState,prec);
}
void BrassPlus::Withdraw(double amt){
format initialState = setFormat();
precis prec = cout.precision(2);
double bal = Balance();
if(amt <= bal){
Brass::Withdraw(amt);
}else if(amt <= bal + maxLoan - owesBank){
double advance = amt - bal;
owesBank += advance * (1.0 + rate);
cout << "Bank advance : $ " << advance << endl;
cout << "Finance charge: $" << advance * rate << endl;
Deposit(advance);
Brass::Withdraw(amt);
}else{
cout << "Credit limit exceeded. Transaction cancelled.\n";
}
restore(initialState,prec);
}
format setFormat(){
return cout.setf(std::ios_base::fixed,std::ios_base::floatfield);
}
void restore(format f,precis p){
cout.setf(f,std::ios_base::floatfield);
cout.precision(p);
}
// main.cpp
#include <iostream>
#include"brass.cpp"
#include<string>
const int CLIENTS = 4;
int main(int, char**) {
using std::cin;
using std::cout;
using std::endl;
Brass * p_clients[CLIENTS];
std::string temp;
long tempnum;
double tempbal;
char kind;
for(int i = 0; i < CLIENTS; i++){
cout << "Enter client's name: ";
getline(cin,temp);
cout << "Enter client's account number: ";
cin >> tempnum;
cout << "Enter opening balance: $";
cin >> tempbal;
cout << "Enter 1 for Brass Account or " << "2 for BrassPlus Account: ";
while(cin>>kind &&(kind !='1' && kind != '2')){
cout << "Enter either 1 or 2: ";
}
if(kind == '1'){
p_clients[i] = new Brass(temp,tempnum,tempbal);
}
else{
double tmax,trate;
cout << "Enter the overdraft limit: $";
cin>> tmax;
cout << "Enter the interest rate " << "as a decimal fraction: ";
cin >> trate;
p_clients[i] = new BrassPlus(temp,tempnum,tempbal,tmax,trate);
}
while(cin.get() != '\n'){
continue;
}
}
cout << endl;
for(int i = 0; i < CLIENTS; i++){
p_clients[i]->ViewAcct();
cout << endl;
}
for(int i = 0; i < CLIENTS; i++){
delete p_clients[i];
}
cout << "Done. \n";
return 0;
}
在上述程序代码中使用delete 释放由 new 分配的对象的代码说明了为何基类应包含一个虚析构函数,虽然有时好像并不需要析构函数。如果析构函数不是虚的,则将只调用对应于指针类型的析构函数。对于上述程序代码,这意味着只有 Brass的析构函数被调用,即使指针指向的是一个 BrassPlus 对象。如果析构函数是虚的,将调用相应对象类型的析构函数。因此,如果指针指向的是 BrassPlus 对象,将调用 BrassPlus的析构函数,然后自动调用基类的析构函数。因此,使用虚析构函数可以确保正确的析构函数序列被调用。对于上述程序代码,这种正确的行为并不是很重要,因为析构函数没有执行任何操作。然而,如果 BrassPlus包含一个执行某些操作的析构函数,则 Brass 必须有一个析构函数,即使该析构函数不执行任何操作。