可能会遇到这种情况,希望同一个方法在派生类和基类中的行为是不同的。这种复杂的行为被称为多态-具有多种形态。有两种重要的机制可以用于实现多态的公有继承:
在派生类中重新定义基类的方法。使用虚方法。
Brass Account支票账户信息:客户姓名 账号 当前结余 可以执行的操作:创建账户 存款 取款 显示信息
BrassPlus Account包含Brass的信息以及:透支上限 透支贷款利率 显示透支总额 有两种的操纵实现不同 取款操作要考虑透支保护 显示操作要显示BrassPlus的信息
class Brass
{
private:
enum {MAx=35};
char fullname[MAX];
long acctNum;
double balance;
public:
Brass(const char *s="Nullbody",long an=-1; double bal=0.0);
void Deopsit(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 char *s="nullbody",long ml=500,double r=0.1);
virtual void ViewAcct() const;
virtual void Withdraw(double amt);
void reseMax(double m){maxLoan=m;}
void ReseRate(double r){rate=r;}
void ReseOwes(){owesBank=0;}
};
BrassPlus类在Brass类基础上添加了3个私有数据成员和3个公有成员函数。
Brass类和BrassPlus类都声明了 ViewAcct()和Withdraw()方法,但是BrassPlus对象和Brass对象的这些方法的行为是不同的。
Brass类在声明ViewAcct()和Withdraw()方法时候使用了virtual关键字。
Brass类还声明一个虚拟析构函数,虽然不执行任何操作。
两个ViewAcct()原型表明将有2个独立的方法定义。基类版本的限定名为Brass::ViewAcct(),派生类的版本限定名为BrassPlus::ViewAcct().程序根据对象类型来确定使用哪个版本。
如果没有使用关键字virtual,程序将根据引用类型或指针类型选择方法;如果使用了virtual,程序将会根据引用或指针指向的对象的类型来选择方法。
基类声明一个虚拟析构函数,这样做为了确保释放对象时,按正确的顺序调用析构函数。
关键字virtual只用于类声明的方法原型中,没有用于方法的定义中。
派生类不能直接范围基类的私有数据,而必须使用基类的公有方法才能访问这些数据。
派生类构造函数在初始化基类私有数据时,采用的是成员初始化列表句法。将基类信息传递给基类构造哈数,然后使用构造函数初始化派生类新增的数据对象。
非构造函数不能使用成员初始化列表语句,派生类可以调用公有的基类方法。
BrassPlus::ViewAcct()显示新增的BrassPlus数据成员,并调用基类方法Brass::ViewAcct()来显示基类数据成员。
代码必须使用作用域解析操作符。
假设同时管理Brass和BrassPlus账户,如果能同时使用一个数组来保存将很有用,但是数组中的元素类型必须是相同的。可以创建指向Brass的指针,这样每个数组元素都是相同的,但由于使用的公有继承,Brass指针可以指向BrassPlus对象,可以使用一个数组指向多种类型的对象。
析构函数是虚拟的,将调用相应对象类型的西沟函数。没有虚构,只调用对应指针类型的虚构函数。 对于Brass类指针数组,则只调用Brass的析构函数。