天天看点

多态公有继承

多态:同一个方法在派生类和基类中的行为是不同的,方法的行为应取决于调用该方法的对象,即同一个方法的行为随上下文而异

  • 在派生类中重新定义基类的方法
  • 使用虚函数
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​

    ​来指出哪些函数是虚函数
  • 基类声明了一个虚析构函数,这样做是为了确保释放派生对象时,按正确的顺序调用析构函数