函數的重載,覆蓋/重寫,與隱藏

1.  函數重載(Overload):編程

普通的重載咱們都知道是怎麼回事。在面向對象的編程中,函數重載只能發生在同一個類當中ide

典型的重載重載就是類的構造函數,好比:無參構造函數,拷貝構造函數,賦值構造函數之間。函數

重載發生的條件是:僅僅函數的形參(數量或者類型)不一樣。spa

 

2. 函數覆蓋/重寫(Override):指針

函數覆蓋(也就是重寫)就是咱們平時所說的類的多態性實現的時候發生的事情:code

基類指針指向派生類,指針調用函數時派生類的函數就會覆蓋基類函數。對象

覆蓋發生的條件,就是多態性實現的條件blog

a.基類指針指向派生類;繼承

b.基類的函數前有virtual聲明爲虛函數;接口

c.基類和派生類(函數名和參數等)徹底相同!

 

3. 函數隱藏(Hide?):

其餘類定義的函數,被類的同名函數屏蔽,好像被隱藏了。

(說成被覆蓋了好像也解釋得通,可是人家規定好「覆蓋」和「隱藏」的意義了,就入鄉隨俗好了)

函數隱藏的條件:

a.首先要同名,否則就不是同一個函數了;

b.不一樣類的同名函數,假如知足函數覆蓋,就會發生函數隱藏!

雖然b聽起來很絕對,可是也很好記,關鍵是正確!

 

4. 舉個栗子好了:

 1 class Base
 2 {
 3 public:
 4     virtual  void  f(float  x) { cout  <<  "Base::f(float)"  <<  endl; }
 5     void  g(float  x) { cout  <<  "Base::g(float)"  <<  endl; }
 6     void  h(float  x) { cout  <<  "Base::h(float)"  <<  endl; }            
 7 }
 8 
 9 class Derive
10 {
11 public:
12     virtual  void  f(float  x) { cout  <<  "Derive::f(float)"  <<  endl; }
13     void  g(int  x)     { cout  <<  "Derive::g(int)"  <<  endl; }
14     void  h(float  x)  { cout  <<  "Derive::h(float)"  <<  endl; }            
15 }

調用:
  Base *base = new Derive;
  base -> f(1.0);
  base -> g(2);
  base -> h(1.0);

會發生什麼?根據上面的規則很好判斷:

先看是否符合多態性的條件,只有Derive::f(float x)符合,因此會發生函數覆蓋;

其餘不符合的,就是發生函數隱藏,也就是因爲指針指向派生類,說此時函數的調用只和派生類有關,和基類沒有關係!

 

 

5. 覆蓋和隱藏的選擇

一間學校,基類是學生,派生類是:小學生,初中生,高中生;

函數有:吃飯,上課,考試;

吃飯是每一個學生都要作的事情,並且作法同樣,都是去食堂吃飯;

考試是部分學生(初高中生)須要作的事情,小學生減負不考試;

上課雖然是每類學生都要作的事情,可是每類學生的作法都不相同;

吃飯,考試,上課,對於每一個派生類的共用性程度愈來愈低,這種狀況下如何設定函數的模式呢?

 

首先,既然每一個派生類都要實現相同的吃飯函數,就把吃飯放在基類中,做爲基類的普通成員函數

派生類繼承基類,天然就能夠正常使用吃飯函數。

這叫作什麼?就是普通的繼承啊~

 

而後,上課是每一個派生類都作可是作法都不相同的函數,很容易想到經過多態性實現。

具體來講就是在基類中聲明上課是虛函數,而後在不一樣派生類中重寫本身的上課函數,進行覆蓋。

最好聲明上課爲純虛函數,就不用在基類中實現上課函數了,由於基類的上課原本就沒有特殊意義,只是一個接口。

這樣基類就成了抽象類,不能實例化。

不過不要緊,咱們建議用指針實現類的實例化和函數調用。

 

最後,有大部分派生類可使用考試函數,可是又不能讓小學生考試,這種狀況下怎麼設定函數模式?

確定不能是基類的普通成員函數,不然怎麼實現?

第一種方法:

在基類中聲明並實現考試函數爲虛函數,在大部分派生類中不定義考試函數進行覆蓋,

只在小學生類中從新定義一個空的考試函數,進行覆蓋以實現多態性

第二種方法:

在基類中定義考試爲普通成員函數,派生類經過繼承使用她。

對於小學生來講,能夠在類中從新定義一個空的考試函數,實現對基類考試函數的隱藏

 

從邏輯性來講,實現多態性會更容易理解一些。

相關文章
相關標籤/搜索