多态:同一个方法在派生类和基类中的行为是不同的,方法的行为应取决于调用该方法的对象,即同一个方法的行为随上下文而异
实现方式:
在派生类中重新定义基类的方法使用虚函数程序示例:
class Brass { private: std::string fullName; long acctNum; double balance; public: Brass(const std::string & s = "Nullbody", long an = -1, double ba1 = 0.0); virtual ~Brass(); void Deposit(double amt); double Balance() const; //================================== virtual void Withdraw(double amt); virtual void ViewAcct() const; //================================== } class BrassPlus : public Brass { private: double maxLoan; double rate; double oweBank; public: BrassPlus(const std::string & s = "Nullbody", long bal = 0.0, double ml = 500, double r = 0.11125); BrassPlus(const Brass & ba, double ml = 500, double r = 0.11125); //================================== virtual void Withdraw(double amt); virtual void ViewAcct() const; //================================== void ResetMax(double m) { maxLoan = m; } void ResetRate(double r) { rate = r; } void ResetOwes() { owesBank = 0; } }类Brass和类BrassPlus都定义了Withdraw()和ViewAcct()方法,程序将根据对象类型来确定使用哪个版本:
Brass dom("Dominic Banker",11224,4183.25); BrassPlus dot("Dominic Banker",12118,2590.25); dom.ViewAcct(); //invoke Brass::ViewAcct() dot.ViewAcct(); //invoke BrassPlus::ViewAcct()如果方法是通过引用或指针而不是对象调用的,它将确定使用哪一种方法。如果没有使用关键字virtual,程序将根据引用类型或指针类型选择方法;如果使用了virtual,程序将根据引用或指针指向的对象的类型来选择方法。
如果ViewAcct()不是虚的,则程序的行为如下:
Brass dom("Dominic Banker",11224,4183.25); BrassPlus dot("Dominic Banker",12118,2590.25); Brass & b1_ref = dom; Brass & b2_red = dot; b1_ref.ViewAcct(); //invoke Brass::ViewAcct() b2_red.ViewAcct(); //invoke Brass::ViewAcct()如果ViewAcct()是虚的,则程序的行为如下:
Brass dom("Dominic Banker",11224,4183.25); BrassPlus dot("Dominic Banker",12118,2590.25); Brass & b1_ref = dom; Brass & b2_red = dot; //invoke Brass::ViewAcct() b1_ref.ViewAcct(); //invoke BrassPlus::ViewAcct() b2_red.ViewAcct();方法在基类中被声明为虚的后,它在派生类中将自动成为虚方法,当然也可以在派生类中使用关键字virtual来指出哪些函数是虚函数
基类声明了一个虚析构函数,这样做是为了确保释放派生对象时,按正确的顺序调用析构函数