1、什么是多态公有继承
希望同一个方法在派生类和基类中的行为是不同的,换句话说,方法的行为应取决于调用该方法的对象。这种较复杂的行为称为多态—-即具有多种形态。
2、如何实现多态
(1)在派生类中重新定义基类的方法
(2)使用虚方法virtual
对于第一种重新定义基类的方法可以参考上一篇博文派生类和基类的关系http://blog.csdn.net/vincentlmeng/article/details/72174657
RatedPlayer类在TableTennisPlayer类的基础上添加新数据成员和新方法成员。
第二种介绍如何指出方法在派生类的行为的不同。其实就是看类的限定名。
比如下面的程序就是通过类的限定名:
Brass dom("Dominic Banker",11224,4183.45);
BrassPlus dot("Dorothy Bankeer",12118,2592.00);
dom.ViewAcct();//use Brass::ViewAcct()
dot.ViewAcct();//use BrasePlus::ViewAcct()
第三种有点复杂使用virtual如果方法使通过引用或指针而不是对象调用的,它将确定使用哪一种方法。
(1)没使用virtual,将根据引用类型或指针类型选择方法。
(2)使用virtual.将根据引用或指针 指向的对象 的类型来选择方法。
看个程序就好明白了
情况(1)没有使用virtual
Brass dom("Dominic Banker",11224,4183.45);
BrassPlus dot("Dorothy Bankeer",12118,2592.00);
Brass & b1_ref=dom;
Brass & b2_ref=dot;
b1_ref.ViewAcct();//use Brass::ViewAcct()
b2_ref.ViewAcct();//use Brass::ViewAcct()
因为引用变量的类型为Brass所以use Brass::ViewAcct()
情况(2)使用virtual void ViewAcct()const
Brass dom("Dominic Banker",11224,4183.45);
BrassPlus dot("Dorothy Bankeer",12118,2592.00);
Brass & b1_ref=dom;
Brass & b2_ref=dot;
b1_ref.ViewAcct();//use Brass::ViewAcct()
b2_ref.ViewAcct();//use BrassPlus::ViewAcct()(敲黑板划重点根据引用的对象的类型选择的dot的类型是BrassPlus)
使用了virtual程序将根据引用的对象的类型来选择方法
第四种基类声明虚析构函数。这样做事为了确保释放派生对象时,按正确的顺序调用析构函数。
#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(){};
};
//Brass Plus Account class
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 m1 = 500, double r = 0.11125);
BrassPlus(const Brass &ba, double m1 = 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
#include<iostream>
#include"brass.h"
#pragma comment(lib,"ws2_32.lib")
using std::cout;
using std::endl;
using std::string;
typedef std::ios_base::fmtflags format;
typedef std::streamsize precis;
format setFormat();
void restore(format f, precis p);
//Brass methods
Brass::Brass(const string &s, long an, double bal)
{
fullName = s;
acctNum = an;
balance = bal;
}
void Brass::Deposit(double amt)
{
if (amt < 0)
cout << "Negative deposit not allowed;"
<< "deposit is cancelled.\n";
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.\n";
else if (amt <= balance)
balance -= amt;
else
cout << "Withdrawal amount of $" << amt
<< "exceeds your balance.\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 methods
BrassPlus::BrassPlus(const string &s, long an, double bal, double m1, double r) :Brass(s, an, bal)
{
maxLoan = m1;//最大透支
owesBank = 0.0;//所欠金额
rate = r;//利率
}
BrassPlus::BrassPlus(const Brass &ba, double m1, double r) :Brass(ba)
{
maxLoan = m1;//最大透支
owesBank = 0.0;//所欠金额
rate = r;//利率
}
//重新定义方法ViewAcct()
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 serFormat()
{
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);
}