c++中派生類函式遮擋(hide)基類中同名函式的問題是比較令人費解的,有必要詳細說明一下。
看看下面一段**:
class base;};
class derived : public base;};
derived *pd = new derived;
pd->f(10);
//編譯錯誤
對於這樣一種情況,scott meyers這樣解釋(effective c++中文第二版 第50條),derived::f遮蔽了base::f,即使兩者的引數型別並不相同。也就是說編譯器不知道有乙個引數型別為int的base::f存在。
但是下面的**卻可以編譯通過:
base *pb = new derived;
pb->f(10);
bjarne stroustrup在arm中對此的解釋是:假設當你呼叫f時,你真正想呼叫的時derived版本,但你意外地使用了錯誤的引數型別(本例為int)。更進一步假設derived是繼承體系中的一員,而且你並不知道derived間接繼承了某個baseclass,後者宣告有乙個虛函式f,需要乙個int引數。這種情況下你將意外呼叫baseclass::f——乙個你甚至並不知道它存在的函式。這種錯誤有可能在大型繼承體系中常常發生,所以stroustrup決定釜底抽薪(好乙個釜底抽薪!)地令derived class members遮蔽同名的base class members。
再看看以下**:
class base
;virtual void f(char* x) {};
};class derived : public base;};
derived *pd = new derived;
pd->f((char*)2); // 編譯錯誤
pd->f(2); // 通過
base *pb = new derived;
pb->f((char*)2); // 通過
pb->f(2); // 通過
根據以上的解釋,應該不難理解這樣的編譯結果。那麼我們看看靜態函式是否一樣的情況。
class base;};
class derived : public base
; //不論此定義前是否有 static,都有以下結果
};derived *pd = new derived;
pd->f(2); // 編譯錯誤
pd->f((void*)2);
// 通過
base *pb = new derived;
pb->f(2); // 通過
pb->f((void*)2); // 錯誤
這樣我們發現對於static函式,一樣存在如上所述的遮蔽作用。c++允許派生類重新定義基類中的任何函式(private除外),這種權力是一把雙刃劍,在給予程式設計師能力的同時也誘導他們犯錯誤。
class base;};
class derived : public base;};
class son : public derived;};
son *ps = new son;
derived *pd = ps;
base *pb = pd;
ps->f(2);
// 呼叫 son::f
pd->f(2);
// 呼叫 son::f
pb->f(2);
// 呼叫 base::f
以上這種在開發繼承層次很多的大型軟體時表現出來的精神**症就很難找到問題根源。
過載 覆蓋和隱藏
部分文字內容摘自 高質量c c程式設計 1 過載 overload 1 相同的範圍,在同乙個類中。2 函式名相同,引數不同。3 virtual可有可無。這在平時設計中用的比較多,比如遊戲中角色說話,可以設計成 void senddialog const char content 預設 void se...
隱藏和覆蓋 C
我可以給你說說我的理解 我認為隱藏和覆蓋的區別主要體現在 多型上 舉個例子 隱藏和覆蓋 include include using namespace std class a void f class b public a virtual void g int main 結果是 a a b invo...
C 覆蓋和隱藏
class people virtual void getname different params 隱藏規則2 1 函式名相同 引數相同 2 無virtual void getphone same params 覆蓋規則 1 函式名相同 引數相同 2 有virtual virtual void g...