11. C++ 遮蔽、覆蓋、過載
11.1過載
在同一個類中,或者在頂層函式(與main函式同層)中,如果函式名相同、引數不一致(型別、個數、順序),則就是函式過載。
函式過載對函式返回值無要求,即返回值可以相同也可以不相同。
例如:
int function(int, char); int function(char, int); int function(int); int function(char);
這四個函式相互之間構成了函式過載。
注意:函式過載返回值可以相同,也可以不相同!
例如:
int function(int, char); char function(int);
構成函式過載
int function(int, char); char(int, char);
這不算是函式過載,與返回值無關
11.2覆蓋(重寫)
函式覆蓋發生在繼承層次之中。
覆蓋需要滿足的條件如下:
(1)發生覆蓋的函式必須分別在父類和子類中
(2)子類函式與父類函式的函式相同,形參一致
(3)父類函式必須是虛擬函式覆蓋對函式返回值同樣沒有要求,可以相同,也可以不同,但是很少有編譯器支援這種特性
class A { …… virtual int function(int, char) { …… } …… }; class B::public A { …… virtual int function(int, char) { …… } …… }; int main(){ A * one; B two; one = & two; one.function(int, char); return 0; }
上面的例子就是一個覆蓋,如果上面沒有關鍵字virtual,那麼呼叫的將會是class A 的函式函式覆蓋說的就是多型。
11.3遮蔽(隱藏)(重定義)
遮蔽是指子類中具有與父類同名的函式(不管引數列表是否相同),除去函式覆蓋的情況。遮蔽的條件:
(1)子類的成員函式與父類的成員函式名必須相同
(2)子類的虛擬函式無法覆蓋父類的虛擬函式遮蔽可以這麼理解:
1)子類成員函式與父類成員函式具有相同的函式名 2)除去覆蓋的情況遮蔽要求函式名一定相同,形參可以相同也可以不相同。 也就是說,繼承層次中,父類與子類同名函式要麼是覆蓋,要麼是遮蔽。
上例中如果沒有virtual關鍵字,就屬於遮蔽情況。或者上例中,子類function函式與父類函式形參不同,則也是遮蔽情況。
#include<iostream> using namespace std; //基類 Peopleclass People{ public: void show(); protected: char *name; int age; }; void People::show(){ cout<<"嗨,大家好,我叫"<<this->name<<",今年"<<this->age<<"歲"<<endl; } //派生類 Studentclass Student: public People{ public: Student(char *name, int age, float score); public: void show(); //遮蔽基類的show() private: float score; }; Student::Student(char *name, int age, float score){ this->name = name; this->age = age; this->score = score; } void Student::show(){ cout<<this->name<<"的年齡是"<<this->age<<",成績是"<<this->score<<endl; } int main(){ Student stu("哈哈", 14, 95.0);//使用的是派生類新增的成員函式,而不是從基類繼承的 stu.show();//使用的是從基類繼承來的成員函式 stu.People::show(); return 0; }
注意:基類成員和派生類成員的名字一樣時會造成遮蔽,不管函式的引數如何。
換句話說,基類成員函式和派生類成員函式不會構成過載,如果派生類有同名函式,那麼就會遮蔽基類中的所有同名函式,不管它們的引數是否一樣。
總結:
(1)函式過載發生在同一個類或頂層函式中,同名的函式具有不同的引數列表
(2)函式覆蓋發生在繼承層次中,該函式在父類中必須是virtual,而子類的該函式必須與父類具有相同的引數列表
(3)函式遮蔽(隱藏)發生在繼承層次中,父類和子類同名的函式中,不屬於函式覆蓋的都屬於函式遮蔽