詳解C++基礎——類繼承中方法重載
一、前言
在上一篇C++基礎博文中討論了C++最基本的代碼重用特性——類繼承,派生類可以在繼承基類元素的同時,添加新的成員和方法。但是沒有考慮一種情況:派生類繼承下來的方法的實現(xiàn)細節(jié)并不一定適合派生類的需求,此時派生類需要重載集成方法。
二、重載方法及虛函數(shù)
我們討論《C++ Primer Plus》中的如下場景:銀行記錄客戶信息,包括客戶姓名、當前余額??蛻暨@一類別當然能夠創(chuàng)建客戶對象、存款、取款以及顯示信息。銀行需要特殊記錄具有透支權限的客戶,因此這一類別的客戶要額外記錄透支上限、透支貸款利率以及當前透支總額。此外,取款和顯示信息兩個操作必須考慮客戶的透支情況。綜上,具有透支權限的客戶是客戶這一基類的派生類,派生類中不但需要添加新的成員,還要重載兩個繼承方法。
類聲明代碼:
#ifndef BRASS_H_
#define BRASS_H_
#include <string>
class Brass
{
private:
std::string fullName;
long acctNum;
double balance;
public:
Brass(const std::string& s = "Nullbody",long an = -1,double ba = 0.0);//default constructor
void Deposit(double amt);
double Balance() const;
virtual void Withdraw(double amt);//virtual function
virtual void ViewAcct() const;
virtual ~Brass() {}//使用虛析構函數(shù)確保先調(diào)用繼承類析構函數(shù)
};
//brass plus account class
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 ResetMax(double m) {maxLoan = m;}//inline function
void ResetRate(double r) {rate = r;}
void ResetOwes() {owesBank = 0;}
};
#endif
brass.h
類方法定義代碼:
#include"brass.h"
#include <iostream>
using std::cout;
using std::endl;
using std::string;
//brass methods
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)
{
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
{
cout << "Client: " << fullName << endl;
cout << "Account Number: " << acctNum << endl;
cout << "Balance: $" << balance << endl;
}
//brassPlus methods
BrassPlus::BrassPlus(const string& 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)
{
maxLoan = ml;
owesBank = 0.0;
rate = r;
}
//redefine viewacct()
void BrassPlus::ViewAcct() const
{
Brass::ViewAcct();
cout << "Maximum loan: $" << maxLoan << endl;
cout << "Owed to bank: $" << owesBank << endl;
}
void BrassPlus::Withdraw(double amt)
{
double bal = Balance();
if(amt <= bal)
Brass::Withdraw(amt);
else if(amt <= bal + maxLoan - owesBank)// 已欠 + 此欠 ≤ maxLoan
{
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);// return to zero
}
else
cout << "Credit limit exceeded. Transcation cancelled.\n" ;
}
brass.cpp
上述代碼多了一個新的語法特性:虛函數(shù)(virtual function)。當基類聲明中函數(shù)前加virtual,表示該函數(shù)為虛函數(shù)。區(qū)別在于當調(diào)用者是引用或者指針時,調(diào)用的是基類方法,還是派生類重載后的方法。具體區(qū)別我們后邊在討論。重中之重在于虛析構函數(shù)的意義。如果程序中使用delete刪除占用的動態(tài)內(nèi)存,且用于索引內(nèi)存地址的指針類型是基類,那么即使該指針指向的是一個派生類對象,此時僅基類析構函數(shù)被調(diào)用。 我們著重觀察brassPlus類重載的方法WithDraw有什么變化。這類客戶由于具有透支權限,在取款時肯定要考慮欠款情況。若欲取出金額≤存儲金額,則直接調(diào)用基類方法WithDraw,把存儲金額減??;若欲取出金額大于存儲金額,就必須進一步分析欠款情況。已欠款+此次欠款≤透支額度時,取款操作才有效。因此:owes+(amt - balance) ≤ maxLoan,進一步變形為:amt ≤ balance+maxLoan-owes。
三、應用程序示例及結(jié)果分析
現(xiàn)在看看應用程序代碼和顯示結(jié)果。APP代碼:
#include <iostream>
#include "brass.h"
int main()
{
using std::cout;
using std::endl;
Brass Piggy("Porcelot Pigg",381299,4000.00);
BrassPlus Hoggy("Horatio Hogg",382288,3000.00);
Piggy.ViewAcct();
cout << endl;
Hoggy.ViewAcct();
cout << endl;
cout << "Depositing $1000 into the Hogg Account:\n";
Hoggy.Deposit(1000.00);
cout << "New balance: $" <<Hoggy.Balance() <<endl;
cout << endl;
cout << "Withdrawing $4200 from the Pigg Account:\n";
Piggy.Withdraw(4200.00);
cout << "Pigg account balance: $" << Piggy.Balance() << endl;
cout << endl;
cout << "Withdrawing $4200 from the Hogg Account:\n";
Hoggy.Withdraw(4200.00);
Hoggy.ViewAcct();
cout << endl;
Brass dom("Dominic Banker",11224,4183.45);
BrassPlus dot("Dorothy Banker",12118,2592.00);
Brass& b1_ref = dom;
Brass& b2_ref = dot;//use BrassPlus::ViewAcct() function
b1_ref.ViewAcct();
cout << endl;
b2_ref.ViewAcct();
cout << endl;
return 0;
}
usebrass.cpp
打印結(jié)果:

Pigg和Hogg分別是基類和派生類對象。當兩種均取款額度超出存儲金額時,Hogg由于具有透支權限,才得以成功完成操作。注意之后創(chuàng)建的兩個對象dom和dot,從調(diào)用ViewAcct()函數(shù)過程中再次體會虛函數(shù)的意義。若沒有使用virtual關鍵字,程序根據(jù)引用或指針的類型選擇使用基類方法還是派生類同名的重載后方法。若使用該關鍵字,則根據(jù)引用或指針所指向?qū)ο蟮念愋蛠磉x擇。程序中,b1_ref和b2_ref均是Brass類引用,但分別是Brass類對象dom和BrassPlus類對象dot的別名,因此使用virtual關鍵字后的ViewAcct()函數(shù),依次調(diào)用基類和派生類方法。
以上所述是小編給大家介紹的C++基礎——類繼承中方法重載詳解整合,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關文章
C語言中6組指針和自增運算符結(jié)合方式的運算順序問題
本文通過代碼實現(xiàn)分析了6種組合:* p++,(* p)++,* (p++),++* p,++( * p), * (++p),需要的朋友可以參考下2015-07-07
C++多態(tài)特性之派生與虛函數(shù)與模板詳細介紹
這篇文章主要介紹了C++多態(tài)的特性派生與虛函數(shù)與模板,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧2022-09-09

