1. 程式人生 > >C++ 虛擬函式;過載與覆蓋;虛繼承

C++ 虛擬函式;過載與覆蓋;虛繼承

1.什麼是虛擬函式

簡單地說,那些被virtual關鍵字修飾的成員函式,就是虛擬函式。虛擬函式的作用,用專業術語來解釋就是實現多型性(Polymorphism),多型性是將介面與實現進行分離;用形象的語言來解釋就是實現一共同的方法,但因個體差異而採用不同的策略。虛擬函式主要通過虛擬函式表(V-Table)來實現。

2.什麼是純虛擬函式

純虛擬函式相當於基類只提供介面而不定義具體實現,在函式聲明後加=0,如:

virtual void Eat() = 0;

3.純虛擬函式和虛擬函式的區別

虛擬函式在派生類裡面也可以覆蓋,也可以不覆蓋的,直接使用基類的實現;但純虛擬函式必須在派生類中實現,因為它只提供了一個介面。

4.1成員函式被過載的特徵
(1)相同的範圍(在同一個類中); 
(2)函式名字相同; 
(3)引數不同; 
(4)virtual 關鍵字可有可無。 
4.2“覆蓋”是指派生類函式覆蓋基類函式,特徵是:
(1)不同的範圍(分別位於派生類與基類); 
(2)函式名字相同; 
(3)引數相同; 
(4)基類函式必須有virtual 關鍵字。 
4.3“隱藏”是指派生類的函式遮蔽了與其同名的基類函式,特徵是:
(1)如果派生類的函式與基類的函式同名,但是引數不同,此時,不論有無virtual關鍵字,基類的函式將被隱藏(注意別與過載混淆)。 
(2)如果派生類的函式與基類的函式同名,但是引數相同,但是基類函式沒有virtual 關鍵字。此時,基類的函式被隱藏(注意別與覆蓋混淆)。


static成員函式不能覆蓋和隱藏

class Base{
public:
 virtual void f(float x){ cout << "Base::f(float) " << x << endl; }
 void g(float x){ cout << "Base::g(float) " << x << endl; }
 void h(float x){ cout << "Base::h(float) " << x << endl; }
};


class Derived : public Base{
public:
 virtual void f(float x){ cout << "Derived::f(float) " << x << endl; }
 void g(int x){ cout << "Derived::g(int) " << x << endl; }
 void h(float x){ cout << "Derived::h(float) " << x << endl; }
};


int main()
{
Derived  d;
 Base *pb = &d;
 Derived *pd = &d;
 pb->f(3.14f); // Derived::f(float) 3.14(覆蓋)


pd->f(3.14f); // Derived::f(float) 3.14(覆蓋)
 

 pb->g(3.14f); //Base::g(float) 3.14(非虛擬函式,直接呼叫基類函式)
 pd->g(3.14f); //Derived::g(int) 3(最佳匹配應該是float,但是因為“隱藏”了所以只能呼叫派生類函式)


 pb->h(3.14f); //Base::h(float) 3.14(非虛擬函式,直接呼叫基類函式)
pd->h(3.14f); //Derived::h(float) 3.14(隱藏)
     
return 0;

}

5.虛繼承和虛基類

虛擬繼承是多重繼承中特有的概念。虛擬基類是為解決多重繼承而出現的。如:類D繼承自類B1、B2,而類B1、B2都繼承自類A,因此在類D中兩次出現類A中的變數和函式,這時會產生二義性。為了解決二義性,同時為了節約記憶體,B1、B2對A的繼承定義為虛擬繼承,而A就成了虛擬基類,這樣D中就只有一份A中的變數和函式。實現的程式碼如下:

class A;

class B1:public virtual A;

class B2:public virtual A;

class D:public B1,public B2;