虛函式與動態繫結

2021-06-07 15:45:47 字數 2270 閱讀 6888

在定義基類時,我們希望基類中的有些函式可以在派生類中重新定義。比如,我們定義了基類記錄的書,可以求出買了多少書花了多少錢;而在派生類中,我們定義的是打折的書,還是要計算買了多少書花了多少錢。這時,就需要重新定義計算錢數的函式了。注意,這裡的重新定義,與之前講過的函式過載或者操作符過載不同:後面兩類,是通過不同的形參,返回值型別來讓編譯器判斷到底使用的是哪個函式,在程式執行前就能判斷;而這裡的重新定義,只是函式體的內容不同,引數、返回值都與積累完全相同。只有程式執行時才能判斷使用的到底是哪個層次中的函式(這個過程成為動態繫結),這樣做是為了讓程式的介面統一。

通過把乙個函式宣告為虛函式,(這個函式不能使這個類的建構函式,也不能是static函式)我們就可以在派生類中重新定義它。虛函式在宣告時,需要加上關鍵字virtual,不能在類的外部出現這個關鍵字。這一點和友元的宣告不同:友元可以既可以在類內不宣告,也可以在類外部宣告。當乙個函式被宣告為虛函式後,這個函式在對於基類的後代而言,就都是虛函式了,不用加上virtual關鍵字。(當然,你也可以加上以強調它是虛函式)。

只有通過基類的引用或者指標呼叫虛函式時,才能發生動態繫結。因為引用或者指標既可以指向基類物件,也可以指向派生類物件的基類部分,用引用或者指標呼叫的虛函式。

舉乙個例子:

class item_base

//返回isbn號

std::string book()

//基類不需要折扣策略

virtual double net_price(std::size_t n)const

//析構函式

virtual ~item_base(){};

private:

std::string isbn;

protected:

double price;

};class bulk_item:public item_base

~bulk_item(){}

double net_price(std::size_t)const;

private:

//買多少書以後才有折扣

std::size_t quantity;

//折扣幅度

double discount;

};

其中:

double bulk_item::net_price(std::size_t cnt)const

我們再定義乙個列印結果的函式:

我們再定義乙個列印結果的函式:我們再定義乙個列印結果的函式:我們再定義乙個列印結果的函式:我們再定義乙個列印結果的函式:

void print_total(std::ostream& os,const item_base& item,std::size_t n)

可以發現,雖然print_total函式的輸入引數是基類的引用,我們能夠也能夠通過派生類來訪問它。當使用基類訪問它時,呼叫的是基類的net_price函式,派生類訪問它時,呼叫的是派生類的net_price函式。這個呼叫規則不是在編譯時可以確定的,必須在程式執行時才能確定。所以稱之為「動態關聯」。與之相對的,是靜態關聯,比如函式的過載,操作符的過載等等。程式執行之前,就能確定呼叫的是哪個函式。

特別的,有時我們會遇到這種情況:我們定義了乙個類,這個類也有自己的資料和函式,但是我們並不希望使用者建立這個類的物件,而只能建立從這個基類派生出的類的物件。有人覺得,既然我們不希望建立乙個乙個類的物件,那麼我們幹嘛要定義這個類呢?其實很多時候,基類,是對一些問題的抽象,對它建立物件是沒有意義的。我們只是用它派生其他的,具體的類。比如,我們建立了「動物」類,定義了動物的「身高」、「體重」,定義了動物的動作:「吃飯」、「睡覺」。從「動物」類派生出「老虎」等類。此時,大家也應該覺得,定義乙個動物類物件沒有多大的意義。

言歸正傳,如何實現上面的構想呢?就是使用純虛函式。純虛函式的定義很簡單,就是在某個函式的形參列表後面加上=0。但這一舉動卻意義非凡:首先我們定義了這個函式(而不是在派生類中定義),是得我們為這類函式提供了統一的、可覆蓋的介面,以便於後面的管理;其次,當乙個類中含有(或者)純虛函式時,這個類就被成為「抽象基類」,我們不能建立這個類的物件,只能用它來派生別的類,建立派生類的物件,這樣規定,也防止我們誤用了這個類(因為他是被用來繼承的,很多成員都不完善。)舉乙個例:

class annimal

;private:

double height;

double weight;

};class tiger:public annimal

{public:

void eat(){std::cout<<"eat meat"<

繫結與虛函式

繫結 程式自身彼此關聯的過程,確定程式中的操作呼叫與執行該操作的 間的關係。靜態繫結 繫結過程出現在編譯階段,用物件名或者類名來限定要呼叫的函式。動態繫結 繫結過程工作在程式執行時執行,在程式執行時才確定將要呼叫的函式。虛函式 虛函式是動態繫結的基礎。是非靜態的成員函式。在類的宣告中,在函式原型之前...

虛函式 多重繼承 動態繫結

class a class b public a class c public b 假設我們定義乙個類b的物件。由於bobject是類b的乙個物件,故bobject包含乙個虛表指標,指向類b的虛表。int main int main int main 程式在執行p vfunc1 時,會發現p是個指標...

虛函式和動態繫結 C 學習

1.什麼是虛成員函式 即其宣告在返回型別的前面帶有關鍵字virtual的類成員函式。定義為virtual的函式是基類期待派生類重新定義的,基類希望派生類繼承的函式不能定義為虛函式。2.動態繫結 通過動態繫結,我們能夠編寫程式使用繼承層次中任意型別的物件,無須關心物件的具體型別。在c 中,通過基類的引...