多态共有继承

多态——具有多种形态。方法的行为应取决于调用该方法的对象。同一个方法的行为随上下文而异。
有两种重要的机制实现多态共有继承:

  • 在派生类中重新定义基类的方法
  • 使用虚方法

下面将具体实现:

类定义

//ss.h

#ifndef MYTIME_H_

#define MYTIME_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() {}



};



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 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 ResstMax(double m) { maxLoan = m; }//重置最大贷款数目

        void RessRate(double r) { rate = r; }//重置利率

        void RessOwes() { owesBank = 0; }//重置欠账为0



};



#endif



基类:Brass   私有数据成员: fullName,acctNum, balance
派生类: BrassPlus   新增派生私有数据成员: maxLoan,rate,owesBank

 
 


函数的具体实现:

//file00.cpp

#include"ss.h"

#include <iostream>



using std::endl;

using std::cout;

using std::string;



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 << "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 positivive;"

               << "withdrawal canceled.\n";

        else if (amt <= balance)

               balance -= amt;

        else

               cout << "Withdrawal amount must of $" << amt

               << "excede your balance.\n"

               << "Withdrawal cancled.\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 Numer:" << 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;

        rate = r;

        owesBank = 0.0;

}



BrassPlus::BrassPlus(const Brass& ba, double ml, double r) : Brass(ba)

{

        maxLoan = ml;

        rate = r;

        owesBank = 0.0;

}



void BrassPlus::ViewAcct() const

{

        format initialState = setFormat();

        precis prec = cout.precision(2);



        Brass::ViewAcct();

        cout << "Maximum loan: $" << maxLoan << endl;

        cout << "Owed to back: $" << owesBank << endl;

        cout.precision(3);

        cout << "Lone 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 execeeded. Transaction cancelled.\n";

        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);

}




  因为派生类不能直接访问基类的私有数据,而必须使用基类公有的方法才能访问这些数据。
  派生类构造函数在初始化基类私有数据时,采用的是成员初始化列表语法。实例的实现方法:
 

BrassPlus::BrassPlus(const string& s, long an, double bal,

        double ml, double r) : Brass(s, an, bal)

{

        maxLoan = ml;

        rate = r;

        owesBank = 0.0;

}



BrassPlus::BrassPlus(const Brass& ba, double ml, double r) : Brass(ba)

{

        maxLoan = ml;

        rate = r;

        owesBank = 0.0;

}


  这几个构造函数都是使用成员初始化列表语法,将基类信息传递给基类构造函数,然后使用构造函数体初始化类新增的数据项。
  非构造函数不能使用成员初始化列表语法,但派生类方法可以调用基类方法。
  同时注意代码使用作用域运算符来调用基类方法。

void BrassPlus::ViewAcct() const

{
        ...      
        ViewAcct();
       ....
}

  如果没有使用作用域解析符,编译器就会认为ViewAcct()BrassPlus::ViewAcct(),这样创建了一个不会终止的递归函数。所以在实现时要加上::


仅使用Brass和BrassPlus类:

//file01.cpp

#include<iostream>

#include"ss.h"



int main()

{

        using std::cout;

        using std::endl;



        Brass piggy("Porcelot Pigg", 381299, 4000.0);

        BrassPlus Hoggy("Horatio Hogg", 382288, 300.0);

        piggy.ViewAcct();

        cout << endl;



        Hoggy.ViewAcct();

        cout << endl;



        cout << "Despositing $1000 into the Hogg Account:\n";

        Hoggy.Deposit(1000.00);

        cout << "New balance: $" << Hoggy.Balance() << endl;

        cout << "Withdrawing $4200 from the Pigg Account:\n";

        piggy.Withdraw(4200.00);

        cout << "Pigg account balance:$" << piggy.Balance() << endl;

        cout << "Withdraw $4200 from the Hoggy Account:\n";

        Hoggy.Withdraw(4200.00);

        Hoggy.ViewAcct();



        return 0;

}



使用虚方法的行为:
 

//file01.cpp

#include<iostream>

#include"ss.h"

const int CLIENTS = 4;



int main()

{

        using std::cin;

        using std::cout;

        using std::endl;



        Brass* p_clients[CLIENTS];//顾客

        std::string temp;//名字

        long tempnum;//临时账号

        double tempbal;//账户余额

        char kind;



        for (int i = 0; i < CLIENTS; i++)

        {

               cout << "Enter client's name:";

               getline(cin,temp);

               cout << "Enter clint'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 thr 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 < CLIENTS; i++)

        {

               p_clients[i]->ViewAcct();

               cout << endl;

        }

        for (int i = 0; i < CLIENTS; i++)

        {

               delete p_clients[i];

        }

        cout << "Done.\n";



        return 0;

}


函数分析——虚析构函数
  使用delete释放由new分配的对象代码说明为何基类应包含一个虚析构函数,虽然有时候用不到。如果虚析构函数不是虚的,那么将只能调用对应指针类型的析构函数。对于以上程序来说,使用delete时,只有Brass的析构函数被调用,即使指针指向的是BrassPlus类型的对象。析构函数是虚的,则将会调用相应对象类型的析构函数。虚构函数可以确保正确的析构函数被调用。
  但是如果BrassPlus包含一个执行某些操作的析构函数,那么Brass必须有一个虚构函数,即使这个虚构函数不执行任何操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值