函數覆蓋

函數覆蓋

函數覆蓋發生在父類與子類之間,其函數名、參數類型、返回值類型必須同父類中的相對應被覆蓋的函數嚴格一致,(只有一種情況下返回值可以不一致,那就是返回自己類的引用或者指針的時候)覆蓋函數和被覆蓋函數只有函數體不同,當派生類對象調用子類中該同名函數時會自動調用子類中的覆蓋版本,而不是父類中的被覆蓋函數版本,這種機制就叫做函數覆蓋。

原理


覆蓋函數,即在子類中用相同的函數名和簽名重寫父類的方法,虛函數,在子類中用相同的函數名和簽名重寫父類的方法(前面有virtual關鍵字)

特性


總結:調用函數的時候,關鍵看對象的類型。
記住是對象的類型,不管是指針還是引用(同樣是對象的類型)。
好了有了對象的類型就好辦了。當你用這個對象(或者是指針、引用)去調用函數時,
1:該對象(實體)即不是指針或引用的形式,可以輕鬆的調用函數。
2:但是當我們用引用或指針形式時,有個問題是區別指針(引用)的類型和指針(引用)所指實體對象的類型。
A:你用指針來調用某函數,若函數是非虛函數,非虛函數是靜態編譯的(即編譯時刻確定的)。也就是說他不會去虛函數表找這個函數(因為不是虛函數),因 此調用的是指針類型的那個類的相關函數。即使派生類有這個函數(這是實際編程時的大忌!!!)。這就是 你的void FunctionA() const ;
B:當你用這個指針去調用一個虛函數時,他就到虛函數表中,找這個名字的函數,從指針所指對象的類型(即派生類)依次向父類走,直到遇到第一個與次匹配的函數名。

實現


class Father
{
public:
void FunctionA() const
{
cout << "This is FunctionA of class Father." << endl;
}
virtual void FunctionB() const
{
cout << "This is FunctionB of class Father." << endl;
}
};
class Child : public Father
{
public:
void FunctionA() const
{
cout << "This is FunctionA of class Child." << endl;
}
virtual void FunctionB() const
{
cout << "This is FunctionB of class Child." << endl;
}
};
2。在將父類對象的指針指向子類對象的時候 Father* father = new Child;
如father->FunctionA(),則執行的是Father中的實現;father->FunctionB(),
則執行的是Child中的實現。
3。如果直接聲明子類對象,Child child;則無論child.FunctionA()還是 child.FunctionB(),執行的都是Child中的實現。
實現條件:
A.發生在不同的範圍(分別位於派生類和基類中);
B.函數名相同;
C.參數相同(個數相同、順序相同、類型相同);
D.基類的同名成員函數必須有關鍵字virtual修飾;