虛函式的預設引數問題

2021-05-18 00:50:02 字數 1813 閱讀 6202

q:

#include

using namespace std;

class base ; 

// 乙個表示幾何形狀的類 

class shape ; 

class rectangle: public shape ; 

class circle: public shape ; 

用圖形來表示是下面這樣: 

shape 

// /  / 

/    / 

rectangle    circle 

現在看看這些指標: 

shape *ps;                      // 靜態型別 = shape* 

shape *pc = new circle;        // 靜態型別 = shape* 

shape *pr = new rectangle;      // 靜態型別 = shape* 

這個例子中, ps, pc,和pr都被宣告為shape指標型別,所以它們都以此作為自己的靜態型別。注意,這和它們真的所指向的物件的型別絕對沒有關係 ---- 它們的靜態型別總是shape*。 

物件的動態型別是由它當前所指的物件的型別決定的。即,物件的動態型別表示它將執行何種行為。上面的例子中,pc的動態型別是circle*,pr的動態型別是rectangle*。至於ps,實際上沒有動態型別,因為它(還)沒有指向任何物件。 

動態型別,顧名思義,可以在程式執行時改變,典型的方法是通過賦值: 

ps = pc;                        // ps的動態型別 

// 現在是circle* 

ps = pr;                        // ps的動態型別 

// 現在是rectangle* 

虛函式是動態繫結的,意思是說,虛函式通過哪個物件被呼叫,具體被呼叫的函式就由那個物件的動態型別決定:

pc->draw(red);                  // 呼叫circle::draw(red) 

pr->draw(red);                  // 呼叫rectangle::draw(red) 

我知道這些都是老掉牙的知識了,你當然也了解虛函式。(如果想知道它們是怎麼實現的,參見條款m24)但是,將虛函式和預設引數值結合起來分析就會產生問題,因為,如上所述,虛函式是動態繫結的,但預設引數是靜態繫結的。這意味著你最終可能呼叫的是乙個定義在派生類,但使用了基類中的預設引數值的虛函式: 

pr->draw();                    // 呼叫rectangle::draw(red)! 

這種情況下,pr的動態型別是rectangle*,所以rectangle的虛函式被呼叫 ---- 正如我們所期望的那樣。rectangle::draw中,預設引數值是green。但是,由於pr的靜態型別是shape*,這個函式呼叫的引數值是從shape類中取得的,而不是rectangle類!所以結果將十分奇怪並且出人意料,因為這個呼叫包含了shape和rectangle類中draw的宣告的組合。你當然不希望自己的軟體以這種方式執行啦;至少,使用者不希望這樣,相信我。 

不用說,ps, pc,和pr都是指標的事實和產生問題的原因無關。如果它們是引用,問題也會繼續存在。問題僅僅出在,draw是乙個虛函式,並且它的乙個預設引數在子類中被重新定義了。 

為什麼c++堅持這種有違常規的做法呢?答案和執行效率有關。如果預設引數值被動態繫結,編譯器就必須想辦法為虛函式在執行時確定合適的預設值,這將比現在採用的在編譯階段確定預設值的機制更慢更複雜。做出這種選擇是想求得速度上的提高和實現上的簡便,所以大家現在才能感受得到程式執行的高效;當然,如果忽視了本條款的建議,就會帶來混亂。 

虛函式預設引數的問題記錄

剛看了看專案裡的問題,對虛函式預設引數的問題有點兒遺忘,翻了翻資料 the result is i is 3 原因 為什麼c 堅持這種有違常規的做法呢?答案和執行效率有關。如果預設引數值被動態繫結,編譯器就必須想辦法為虛函式在執行時確定合適的預設值,這將比現在採用的在編譯階段確定預設值的機制更慢更複...

C 中 虛函式中的預設引數問題

原文 nwplei的部落格 當通過指標呼叫乙個物件的方法時,如果該方法是虛函式,則實際呼叫的是該例項的方法。當預設引數和虛函式一起出現的時候到底用哪個預設值呢?虛函式是動態繫結的,但是為了執行效率,預設引數是靜態繫結的。也就是 指標是哪種型別,就呼叫該型別對應的類中,該函式定義時的預設值。inclu...

C 中 虛函式中的預設引數問題

當通過指標呼叫乙個物件的方法時,如果該方法是虛函式,則實際呼叫的是該例項的方法。當預設引數和虛函式一起出現的時候到底用哪個預設值呢?虛函式是動態繫結的,但是為了執行效率,預設引數是靜態繫結的。也就是 指標是哪種型別,就呼叫該型別對應的類中,該函式定義時的預設值。include using names...