基類定義了一個虛函數 ,派生類如果重寫該方法 (函數名稱和函數參數列表與積累一致 )則在使用派生類對象給基類指針或者引用賦值的時候,採用基類指針或者引用調用該函數時,會出現動態調用派生類 這是c++的多態特性!
#include<iostream>
using namespace std;
class A
{
public:
virtual void Fun()
{
cout<<"A::Fun()"<<endl;
}
};
class B :public A
{
public:
void Fun(double b)
{
cout<<"B::Fun()"<<endl;
}
//virtual void Fun(double b) 不管有沒有定義成虛函數
//會隱藏基類的void
Fun()函數 在主函數中使用B的指針調用
//不含參數的Fun函數會產生變異錯誤。
};
class C : public B
{
public:
void Fun(int c)
{
cout<<"C::Fun()"<<endl;
}
//同理 即使B中將virtual void Fun(double b) 定義成虛函數
//C定義的 void Fun(int c)會隱藏類B的void Fun(double b)函數 在主函數中使用B的指針調用//將C對象賦值給B的指針或者引用 再用該指針或者引用 調用Fun函數會產生只會調用類///B中的Fun函數。而C從B中繼承的虛函數就被隱藏了。
};int main()
{
C c;
A& a=c;
B& b=c;
a.Fun();
b.Fun(1);
return 0;
}
輸出結果爲:
A::Fun()
B::Fun()
總結:c++中派生類重新定義不會生成函數的兩個重載版本。而是隱藏了基類中的版本。簡而言之:重新定義繼承的方法不是重載。如果在派生類中重新定義函數,將不是使用相同的函數特性標覆蓋基類的申明,而是隱藏同名的基類方法。
這就有兩點必須注意了:
1、如果派生類重定義基類繼承的方法,應確保與原來的原型完全相同。但如果返回類型的是基類引用或者指針,則可以修改爲指向派生類的引用或者指針。這種特性被稱爲返回型協變。
class A
{
public:
virtual A& Show()
{
cout<<"A::Show()"<<endl;
return *this;
}
};
class B:public A
{
public:
virtual B& Show()
{
cout<<"B::Show()"<<endl;
return *this;
}
};
在主函數中 定義 B b;
A& a=b;
a.Fun();
輸出的是 B::Show()
2、如果基類中的虛函數被其他虛函數重載了,則應在在派生類中重新定義所有的基類版本。
不然會隱藏沒有定義的基類版本。