深度理解派生与多态
利用C++進行編程都了解,面向?qū)ο缶幊袒谌齻€基本的概念:數(shù)據(jù)抽象、繼承和動態(tài)綁定。在C++中,用類進行數(shù)據(jù)抽象,用類派生從一個類繼承另外一個:派生類繼承基類的成員。動態(tài)綁定使編譯器能夠在運行時決定是使用基類定義的函數(shù)還是派生類中定義的函數(shù)。
許多應(yīng)用程序的特性可以用一些相關(guān)但略有不同的概念來描述。例如,書店可以用不同的書提供不同的定價策略,有些書只能按照給定價格出售,另一些書可以根據(jù)折扣策略出售。
面向?qū)ο缶幊?#xff08;object-oriented programming,oop)與這種應(yīng)用非常匹配。通過集成可以定義一些類型,以模擬不同種類的書,通過動態(tài)綁定編寫程序,來實現(xiàn)這其中的差異!
1. 概述
面向?qū)ο缶幊痰年P(guān)鍵思想是多態(tài)性(polymorphism)。 繼承是指通過繼承我們能夠定義這樣的類,他們對類型之間的關(guān)系建模,共享公共的東西,僅僅特化本質(zhì)上不同的東西。派生類(derived class)能夠繼承基類(base class)定義的成員,派生類可以無須改變而是用那些與派生類型具體特性不相關(guān)的操作,派生類可以無需改變而使用那些與派生類型具體特性不相關(guān)的操作,派生類可以重定義那些與派生類型相關(guān)的成員函數(shù),將函數(shù)特化。 實例: #include <iostream> #include <string> using namespace std;class Item_Based { public: Item_Based(const string &book,double sale_price){ isbn = book; price = sale_price; }string book () const { return isbn; }virtual double net_price(size_t n) const //???? the function of "const"{ return n * price; } private:string isbn; protected: double price; };class Bulk_Item: public Item_Based { public:Bulk_Item(const string &book ,double sale_price,size_t qty,double dscnt):Item_Based(book,sale_price) //Based class Initialized{min_qty = qty; discount = dscnt;}virtual double net_price(size_t ) const; //????????? private:size_t min_qty; // minimum purchase for discount to applydouble discount; // fractional discount to apply};inline double Bulk_Item::net_price(size_t cnt) const {if (cnt >= min_qty){ return (1-discount)*price*cnt; } else{ return price*cnt; } }void print_total(ostream &os,Item_Based &item, size_t n) {os << "ISBN: ";os << item.book(); //operate overloados << "\tnumber sold: " ;os << n << "\ttotal price: ";os << item.net_price(n);os <<endl;//why the part didn't do derived net_price } int main() {Item_Based base("DaoMuBiJi",30);Bulk_Item derived("LaoJiuMen",30,2,0.5);// print_total makes a virtual call to net_priceprint_total(cout,base,10); // calls Item_base::net_priceprint_total(cout,derived,10); // calls Bulk_item::net_price }程序運行結(jié)果: 說明:1.雖然外接函數(shù)的第二個參數(shù)是Item_Base的引用,但是我們可以將Item_Base對象或者Bulk_Item對象傳給它 ? ? ? ? ? ?2.因為形參是引用且net_price是虛函數(shù),所以對net_price的調(diào)用將在運行時確定。調(diào)用哪個版本的net_price將在運行時確定!調(diào)用哪個版本net_price將依賴于傳給print_tatal的實參!如果傳給print_total的實參是Bulk_Item對像,將運行Bluk_Item中定義的應(yīng)用折扣net_price;如果實參是一個Item_Base對象,則調(diào)用Item_Base定義的版本。 核心:在C++中,通過基類的引用或指針調(diào)用虛函數(shù)時,將發(fā)生動態(tài)綁定。引用(或指針)即可以指向基類對象也可以指向派生類對象,這一個事實是動態(tài)綁定的關(guān)鍵!!!用引用或指針調(diào)用的虛函數(shù)在運行時確定。(需要強調(diào)一點的是:基類的虛函數(shù)與派生類的虛函數(shù)定義必須一模一樣。。。由于在派生類中,我丟掉了const標識符,導(dǎo)致我一度的懷疑,動態(tài)綁定的可行性)2.訪問情況
在基類中,public 和 private 標號具有普通含義:用戶代碼可以訪問類的public 成員而不能訪問 private 成員, private 成員只能由基類的成員和友元訪問。派生類對基類的 public 和 private 成員的訪問權(quán)限與程序中任意其他部分一樣:它可以訪問 public 成員而不能訪問 private 成員。 這里需要強調(diào)一點的是protected(受保護的訪問標號)。protected成員可以被派生類對象訪問,但不能被該類型的普通用戶訪問。 可以認為 protected 訪問標號是 private 和 public 的混合:? 像 private 成員一樣,protected 成員不能被類的用戶訪問。
? 像 public 成員一樣,protected 成員可被該類的派生類訪問。 需要再次強調(diào)的是:一旦函數(shù)在基類中聲明為虛函數(shù),他就一直為虛函數(shù),派生類無法改變該函數(shù)為虛函數(shù)這一事實,派生類重定義虛函數(shù)時,可以用virtual保留字,但是不是必須這樣做!
3.virtual與其他成員函數(shù)
C++ 中的函數(shù)調(diào)用默認不使用動態(tài)綁定。要觸發(fā)動態(tài)綁定,滿足兩個條件:第一,只有指定為虛函數(shù)的成員函數(shù)才能進行動態(tài)綁定,成員函數(shù)默認為非虛函數(shù),非虛函數(shù)不進行動態(tài)綁定;第二,必須通過基類類型的引用或指針進行函數(shù)調(diào)用。
總結(jié)
- 上一篇: [多图]Google Chrome漫画书
- 下一篇: 飞鸽传书10048错误的解决