类的继承复习(啥都不会了。。。)(二)

简介: 类的继承复习(啥都不会了。。。)

4.多态

     如果没有使用关键字virtual,程序根据引用类型或指针类型选择方法;如果用了virtual,程序将根据引用或指针指向的对象的类型来选择方法。

view plaincopy to clipboardprint?
Brass dom(...);   
BrassPlus dot(...);   
Brass & b1 = dom;   
Brass & b2 = dot;   
//behavior with non-virtual ViewAcct()   
b1.ViewAcct();   // use Brass::ViewAcct()   
b2.ViewAcct();   // use Brass::ViewAcct()   
//behavior with virtual ViewAcct()   
b1.ViewAcct();   // use Brass::ViewAcct()   
b2.ViewAcct();   // use BrassPlus::ViewAcct()  
Brass dom(...);
BrassPlus dot(...);
Brass & b1 = dom;
Brass & b2 = dot;
//behavior with non-virtual ViewAcct()
b1.ViewAcct();   // use Brass::ViewAcct()
b2.ViewAcct();   // use Brass::ViewAcct()
//behavior with virtual ViewAcct()
b1.ViewAcct();   // use Brass::ViewAcct()
b2.ViewAcct();   // use BrassPlus::ViewAcct() 

 非构造函数不能使用成员初始化列表句法,但派生类方法可以调用公有的基类方法。在派生类方法中,标准的技术是使用作用域解析操作符来调用基类方法。如

view plaincopy to clipboardprint?
void BrassPlus::ViewAcct() const  
{   
   ...   
   Brass::ViewAcct();   
   ...   
}  
void BrassPlus::ViewAcct() const
{
   ...
   Brass::ViewAcct();
   ...
} 

如果写成void BrassPlus::ViewAcct() const{   ...   ViewAcct();   ...}将创建一个不会终止的递归函数。不过如果派生类没有重新定义某基类的方法,则代码不必对该方法使用作用域解析操作符。

     假设要同时管理Brass和BrassPlus账户,如果能使用同一个数组来保存Brass和BrassPlus对象,将很有帮助,但这是不可能的,数组中所有元素的类型必须相同。不过,可以创建指向Brass的指针数组,这样,每个元素的类型都相同,但由于是公有继承模型,因此Brass指针既可以指向Brass对象,也可以指向BrassPlus对象。因此,可以使用一个数组来表示多种类型的对象,这就是多态性。

     下面是一个多态的例子:

view plaincopy to clipboardprint?
// brass.h  -- bank account classes   
#ifndef BRASS_H_   
#define BRASS_H_   
// Brass Account Class   
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 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 char *s = "Nullbody", long an = -1,   
            double bal = 0.0, double ml = 500,   
            double r = 0.10);   
    BrassPlus(const Brass & ba, double ml = 500, double r = 0.1);   
    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  
// brass.h  -- bank account classes
#ifndef BRASS_H_
#define BRASS_H_
// Brass Account Class
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 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 char *s = "Nullbody", long an = -1,
            double bal = 0.0, double ml = 500,
            double r = 0.10);
    BrassPlus(const Brass & ba, double ml = 500, double r = 0.1);
    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 
view plaincopy to clipboardprint?
// brass.cpp -- bank account class methods   
#include <iostream>   
#include <cstring>   
#include "brass.h"   
using std::cout;   
using std::ios_base;   
using std::endl;   
// Brass methods   
Brass::Brass(const char *s, long an, double bal)   
{   
    std::strncpy(fullName, s, MAX - 1);   
    fullName[MAX - 1] = '\0';   
    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)   
{   
    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";   
}   
double Brass::Balance() const  
{   
    return balance;   
}   
void Brass::ViewAcct() const  
{   
    // set up ###.## format   
    ios_base::fmtflags initialState =   
        cout.setf(ios_base::fixed, ios_base::floatfield);   
    cout.setf(ios_base::showpoint);   
    cout.precision(2);   
    cout << "Client: " << fullName << endl;   
    cout << "Account Number: " << acctNum << endl;   
    cout << "Balance: $" << balance << endl;   
    cout.setf(initialState); // restore original format   
}   
// BrassPlus Methods   
BrassPlus::BrassPlus(const char *s, long an, double bal,   
           double ml, double r) : Brass(s, an, bal)   
{   
    maxLoan = ml;   
    owesBank = 0.0;   
    rate = r;   
}   
BrassPlus::BrassPlus(const Brass & ba, double ml, double r)   
           : Brass(ba)   // uses implicit copy constructor   
{   
    maxLoan = ml;   
    owesBank = 0.0;   
    rate = r;   
}   
// redefine how ViewAcct() works   
void BrassPlus::ViewAcct() const  
{   
    // set up ###.## format   
    ios_base::fmtflags initialState =   
        cout.setf(ios_base::fixed, ios_base::floatfield);   
    cout.setf(ios_base::showpoint);   
    cout.precision(2);   
    Brass::ViewAcct();   // display base portion   
    cout << "Maximum loan: $" << maxLoan << endl;   
    cout << "Owed to bank: $" << owesBank << endl;   
    cout << "Loan Rate: " << 100 * rate << "%\n";   
    cout.setf(initialState);    
}   
// redefine how Withdraw() works   
void BrassPlus::Withdraw(double amt)   
{   
    // set up ###.## format   
    ios_base::fmtflags initialState =   
        cout.setf(ios_base::fixed, ios_base::floatfield);   
    cout.setf(ios_base::showpoint);   
    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";   
    cout.setf(initialState);    
}  
// brass.cpp -- bank account class methods
#include <iostream>
#include <cstring>
#include "brass.h"
using std::cout;
using std::ios_base;
using std::endl;
// Brass methods
Brass::Brass(const char *s, long an, double bal)
{
    std::strncpy(fullName, s, MAX - 1);
    fullName[MAX - 1] = '\0';
    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)
{
    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";
}
double Brass::Balance() const
{
    return balance;
}
void Brass::ViewAcct() const
{
    // set up ###.## format
    ios_base::fmtflags initialState =
        cout.setf(ios_base::fixed, ios_base::floatfield);
    cout.setf(ios_base::showpoint);
    cout.precision(2);
    cout << "Client: " << fullName << endl;
    cout << "Account Number: " << acctNum << endl;
    cout << "Balance: $" << balance << endl;
    cout.setf(initialState); // restore original format
}
// BrassPlus Methods
BrassPlus::BrassPlus(const char *s, long an, double bal,
           double ml, double r) : Brass(s, an, bal)
{
    maxLoan = ml;
    owesBank = 0.0;
    rate = r;
}
BrassPlus::BrassPlus(const Brass & ba, double ml, double r)
           : Brass(ba)   // uses implicit copy constructor
{
    maxLoan = ml;
    owesBank = 0.0;
    rate = r;
}
// redefine how ViewAcct() works
void BrassPlus::ViewAcct() const
{
    // set up ###.## format
    ios_base::fmtflags initialState =
        cout.setf(ios_base::fixed, ios_base::floatfield);
    cout.setf(ios_base::showpoint);
    cout.precision(2);
    Brass::ViewAcct();   // display base portion
    cout << "Maximum loan: $" << maxLoan << endl;
    cout << "Owed to bank: $" << owesBank << endl;
    cout << "Loan Rate: " << 100 * rate << "%\n";
    cout.setf(initialState); 
}
// redefine how Withdraw() works
void BrassPlus::Withdraw(double amt)
{
    // set up ###.## format
    ios_base::fmtflags initialState =
        cout.setf(ios_base::fixed, ios_base::floatfield);
    cout.setf(ios_base::showpoint);
    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";
    cout.setf(initialState); 
}
view plaincopy to clipboardprint?
// usebrass2.cpp -- polymorphic example   
// compile with brass.cpp   
#include <iostream>   
#include "brass.h"   
const int CLIENTS = 4;   
const int LEN = 40;   
int main()   
{   
   using std::cin;   
   using std::cout;   
   using std::endl;   
   Brass * p_clients[CLIENTS];   
   int i;   
   for (i = 0; i < CLIENTS; i++)   
   {   
       char temp[LEN];   
       long tempnum;   
       double tempbal;   
       char kind;   
       cout << "Enter client's name: ";   
       cin.getline(temp, LEN);   
       cout << "Enter client'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  = new Brass(temp, tempnum, tempbal);   
       else  
       {   
           double tmax, trate;   
           cout << "Enter the overdraft limit: $";   
           cin >> tmax;   
           cout << "Enter the interest rate "  
                << "as a decimal fraction: ";   
           cin >> trate;   
           p_clients  = new BrassPlus(temp, tempnum, tempbal,   
                                        tmax, trate);   
        }   
        while (cin.get() != '\n')   
            continue;   
   }   
   cout << endl;   
   for (i = 0; i < CLIENTS; i++)   
   {   
       p_clients ->ViewAcct();   
       cout << endl;   
   }   
   for (i = 0; i < CLIENTS; i++)   
   {   
       delete p_clients ;  // free memory   
   }   
   cout << "Done.\n";            
   return 0;    
}  
// usebrass2.cpp -- polymorphic example
// compile with brass.cpp
#include <iostream>
#include "brass.h"
const int CLIENTS = 4;
const int LEN = 40;
int main()
{
   using std::cin;
   using std::cout;
   using std::endl;
   Brass * p_clients[CLIENTS];
   int i;
   for (i = 0; i < CLIENTS; i++)
   {
       char temp[LEN];
       long tempnum;
       double tempbal;
       char kind;
       cout << "Enter client's name: ";
       cin.getline(temp, LEN);
       cout << "Enter client'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  = new Brass(temp, tempnum, tempbal);
       else
       {
           double tmax, trate;
           cout << "Enter the overdraft limit: $";
           cin >> tmax;
           cout << "Enter the interest rate "
                << "as a decimal fraction: ";
           cin >> trate;
           p_clients  = new BrassPlus(temp, tempnum, tempbal,
                                        tmax, trate);
        }
        while (cin.get() != '\n')
            continue;
   }
   cout << endl;
   for (i = 0; i < CLIENTS; i++)
   {
       p_clients ->ViewAcct();
       cout << endl;
   }
   for (i = 0; i < CLIENTS; i++)
   {
       delete p_clients ;  // free memory
   }
   cout << "Done.\n";         
   return 0; 
}
相关文章
|
8月前
|
存储 编译器 C语言
从C语言到C++_22(继承)多继承与菱形继承+笔试选择题(下)
从C语言到C++_22(继承)多继承与菱形继承+笔试选择题
64 1
|
8月前
|
Java 编译器 定位技术
从C语言到C++_22(继承)多继承与菱形继承+笔试选择题(中)
从C语言到C++_22(继承)多继承与菱形继承+笔试选择题
58 0
|
8月前
|
安全 程序员 C语言
从C语言到C++_22(继承)多继承与菱形继承+笔试选择题(上)
从C语言到C++_22(继承)多继承与菱形继承+笔试选择题
74 0
C++学习笔记_03类的继承 2021-04-15
C++学习笔记_03类的继承 2021-04-15
|
8月前
|
C++
C++零基础教程(类的继承)
C++零基础教程(类的继承)
79 0
类的继承学习记录
类的继承学习记录
76 0
类的继承学习记录
|
存储 编译器 C++
【C++知识点】多态
【C++知识点】多态
99 0
|
存储 设计模式 编译器
【C++】面试官:你小子,继承与多态的题你都会(上)
【C++】面试官:你小子,继承与多态的题你都会(上)
164 0
|
存储 编译器 C++
【C++】面试官:你小子,继承与多态的题你都会(下)
【C++】面试官:你小子,继承与多态的题你都会(下)
121 0
|
程序员 编译器 C++
黑马程序员C++类和对象【6】—— 继承(一文万字带你搞懂C++继承 —— 你还不知道怎么学C++继承吗?不知道虚继承底层原理吗?)(1)
黑马程序员C++类和对象【6】—— 继承(一文万字带你搞懂C++继承 —— 你还不知道怎么学C++继承吗?不知道虚继承底层原理吗?)(1)
212 0
黑马程序员C++类和对象【6】—— 继承(一文万字带你搞懂C++继承 —— 你还不知道怎么学C++继承吗?不知道虚继承底层原理吗?)(1)