詳解C++基礎(chǔ)——類繼承中方法重載
一、前言
在上一篇C++基礎(chǔ)博文中討論了C++最基本的代碼重用特性——類繼承,派生類可以在繼承基類元素的同時(shí),添加新的成員和方法。但是沒有考慮一種情況:派生類繼承下來(lái)的方法的實(shí)現(xiàn)細(xì)節(jié)并不一定適合派生類的需求,此時(shí)派生類需要重載集成方法。
二、重載方法及虛函數(shù)
我們討論《C++ Primer Plus》中的如下場(chǎng)景:銀行記錄客戶信息,包括客戶姓名、當(dāng)前余額??蛻暨@一類別當(dāng)然能夠創(chuàng)建客戶對(duì)象、存款、取款以及顯示信息。銀行需要特殊記錄具有透支權(quán)限的客戶,因此這一類別的客戶要額外記錄透支上限、透支貸款利率以及當(dāng)前透支總額。此外,取款和顯示信息兩個(gè)操作必須考慮客戶的透支情況。綜上,具有透支權(quán)限的客戶是客戶這一基類的派生類,派生類中不但需要添加新的成員,還要重載兩個(gè)繼承方法。
類聲明代碼:
#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() {}//使用虛析構(gòu)函數(shù)確保先調(diào)用繼承類析構(gòu)函數(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
上述代碼多了一個(gè)新的語(yǔ)法特性:虛函數(shù)(virtual function)。當(dāng)基類聲明中函數(shù)前加virtual,表示該函數(shù)為虛函數(shù)。區(qū)別在于當(dāng)調(diào)用者是引用或者指針時(shí),調(diào)用的是基類方法,還是派生類重載后的方法。具體區(qū)別我們后邊在討論。重中之重在于虛析構(gòu)函數(shù)的意義。如果程序中使用delete刪除占用的動(dòng)態(tài)內(nèi)存,且用于索引內(nèi)存地址的指針類型是基類,那么即使該指針指向的是一個(gè)派生類對(duì)象,此時(shí)僅基類析構(gòu)函數(shù)被調(diào)用。 我們著重觀察brassPlus類重載的方法WithDraw有什么變化。這類客戶由于具有透支權(quán)限,在取款時(shí)肯定要考慮欠款情況。若欲取出金額≤存儲(chǔ)金額,則直接調(diào)用基類方法WithDraw,把存儲(chǔ)金額減小;若欲取出金額大于存儲(chǔ)金額,就必須進(jìn)一步分析欠款情況。已欠款+此次欠款≤透支額度時(shí),取款操作才有效。因此:owes+(amt - balance) ≤ maxLoan,進(jìn)一步變形為:amt ≤ balance+maxLoan-owes。
三、應(yīng)用程序示例及結(jié)果分析
現(xiàn)在看看應(yīng)用程序代碼和顯示結(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分別是基類和派生類對(duì)象。當(dāng)兩種均取款額度超出存儲(chǔ)金額時(shí),Hogg由于具有透支權(quán)限,才得以成功完成操作。注意之后創(chuàng)建的兩個(gè)對(duì)象dom和dot,從調(diào)用ViewAcct()函數(shù)過程中再次體會(huì)虛函數(shù)的意義。若沒有使用virtual關(guān)鍵字,程序根據(jù)引用或指針的類型選擇使用基類方法還是派生類同名的重載后方法。若使用該關(guān)鍵字,則根據(jù)引用或指針?biāo)赶驅(qū)ο蟮念愋蛠?lái)選擇。程序中,b1_ref和b2_ref均是Brass類引用,但分別是Brass類對(duì)象dom和BrassPlus類對(duì)象dot的別名,因此使用virtual關(guān)鍵字后的ViewAcct()函數(shù),依次調(diào)用基類和派生類方法。
以上所述是小編給大家介紹的C++基礎(chǔ)——類繼承中方法重載詳解整合,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
C++ 中"emplace_back" 與 "push_back" 的區(qū)別
這篇文章主要介紹了C++ 中"emplace_back" 與 "push_back" 的區(qū)別的相關(guān)資料,需要的朋友可以參考下2017-04-04C語(yǔ)言指針之必須要掌握的指針基礎(chǔ)知識(shí)
這篇文章主要介紹了C語(yǔ)言指針必須要掌握的基礎(chǔ)知識(shí),文中實(shí)例講解的很清晰,有不太懂的同學(xué)可以研究下,希望能夠給你帶來(lái)幫助2021-09-09C++使用expected實(shí)現(xiàn)優(yōu)雅的錯(cuò)誤處理
C++ 中提供了很多中方式進(jìn)行錯(cuò)誤處理。無(wú)論是通過拋異常還是通過錯(cuò)誤碼,標(biāo)準(zhǔn)庫(kù)都提供相應(yīng)的調(diào)用,今天本文為大家介紹的是使用expected進(jìn)行錯(cuò)誤處理,感興趣的可以了解一下2023-06-06C++面試題之?dāng)?shù)a、b的值互換(不使用中間變量)
這篇文章主要介紹了不使用中間變量,C++實(shí)現(xiàn)數(shù)a、b的值互相轉(zhuǎn)換操作,感興趣的小伙伴們可以參考一下2016-07-07