有的时候,派生类使用基类的方法的时候,是和基类使用这个方法的行为时不同的,换句话说,方法的行为取决于调用改方法的对象,这种行为叫做多态继承,通常有两种方法:
1:在派生类中重新定义基类的方法。
2:使用徐方法。
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="no name",long an=-1,double bal=0);
void Deposit(double amt);
virtual void Withdraw(double amt); //虚方法,关键字virtual
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="no name",long an=-1,double bal=0,double ml=500,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 ma){maxLoan=ma;}
void ResetRate(double r){rate=r;}
void ResetOwes(){owesBank=0;}
};
#endif
从头文件中可以看出,派生类添加了3个私有数据成员和3个公有成员函数,另外,brass类在声明ViewAcct() Withdraw()的时候使用了新的关键字virtual,这就是所谓的虚方法。
虚方法这种行为很方便,经常在基类中将派生类会重新定义的方法声明为虚方法。方法在基类中被声明为虚的后,它在派生类中将自动成为虚方法,然后就可以在派生类中进行重新定义。
下面重点讲一下他的调用:
1:使用成员限定符 . 就没有什么好说的了,那个调用他,就用那个定义的方法。例如dom.ViewAcct();
2:如果方法是通过引用或指针类型选择方法,则按照引用类型或者指针指向的类型在使用该种类型的方法,例如:
Brass dom("wang",11111,121);
BrassPlus dot("zhang",2222,112);
Brass &b1_ref=dom;
Brass &b2_ref=dot;
b1_ref.ViewAcct();
b2_ref.ViewAcct();
由于ViewAcct()是虚方法,这时候,b1_ref调用的是Brass::ViewAcct(); b2_ref调用的是BrassPlus::ViewAcct();因为,b1_ref引用的是Brass对象,而b2_ref引用的是BrassPlus对象。但是,如果ViewAcct不是虚方法,即基类定义他的时候没有用virtual关键字,那么,这个时候,b1_ref和 b2_ref都将调用的是Brass::ViewAcct(); 因为两个引用类型都是Brass.
brass.cpp
#include"brass.h"
#include<iostream>
using namespace std;
typedef std::ios_base::fmtflags format;
typedef std::streamsize precis;
format setFormat();
void restore(format f,precis p);
Brass::Brass(const string &s,long an,double bal)
{
fullname=s;
acctNum=an;
balance=bal;
}
void Brass::Deposit(double amt)
{
if(amt<0)
cout<<"Negetive deposit not allowed; deposit is cancelled."<<endl;
else
balance+=amt;
}
void Brass::Withdraw(double amt)
{
format initialState=setFormat();
precis prec=cout.precision(2);
if(amt<0)
cout<<"Withdrawal amount must be positive; withdrawal canceled."<<endl;
else if(amt<=balance)
balance-=amt;
else
cout<<"Withdrawal amount if $"<<amt<<" exceeds your balance.\n"<<"Withfrawal canceled."<<endl;
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<<"%"<<endl;
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; //这时候 余额是4000
Deposit(advance); //这时候,余额就变成4200了,目的是为了使用Withdraw函数,使余额为0
Brass::Withdraw(amt); //这时候余额就变成0了
}
else
cout<<"Credit limit exceeded.Transaction cancelled."<<endl;
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);
}
usebrass2.cpp
#include<iostream>
#include"brass.h"
#include<string>
const int CLUENTS=4;
int main()
{
using namespace std;
Brass * p_clients[CLUENTS];
string temp;
long tempnum;
double tempbal;
char kind;
for(int i=0;i<CLUENTS;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<CLUENTS;i++)
{
p_clients[i]->ViewAcct();
cout<<endl;
}
for(int i=0;i<CLUENTS;i++)
{
delete p_clients[i];
}
cout<<"Done."<<endl;
system("pause");
return 0;
}