1. 程式人生 > >將解構函式設定為虛擬函式,並且解構函式可以為純虛擬函式

將解構函式設定為虛擬函式,並且解構函式可以為純虛擬函式

為什麼基類的解構函式是虛擬函式?

  在實現多型時,當用基類操作派生類,在析構時防止只析構基類而不析構派生類的狀況發生。

但如果不需要基類對派生類及物件進行操作,則不能定義虛擬函式,因為這樣會增加記憶體開銷.當類裡面有定義虛擬函式的時候,編譯器會給類新增一個虛擬函式表,裡面來存放虛擬函式指標,這樣就會增加類的儲存空間.所以,只有當一個類被用來作為基類的時候,才把解構函式寫成虛擬函式.

為什麼解構函式可以是純虛擬函式?

在某些類裡宣告純虛解構函式很方便。純虛擬函式將產生抽象類——不能例項化的類(即不能建立此型別的物件)。有些時候,你想使一個類成為抽象類,但剛好又沒有任何純虛擬函式。怎麼辦?因為抽象類是準備被用做基類的,基類必須要有一個虛解構函式,純虛擬函式會產生抽象類,所以方法很簡單:在想要成為抽象類的類裡宣告一個純虛解構函式。

 class Test {

  public:

       virtual ~Test() = 0; // 宣告一個純虛解構函式

             };

這個類有一個純虛擬函式,所以它是抽象的,而且它有一個虛解構函式,所以不會產生解構函式問題。但這裡還有一件事:必須提供純虛解構函式的定義:

          Test::~Test() {} // 純虛解構函式的定義

這個定義是必需的,因為虛解構函式工作的方式是:最底層的派生類的解構函式最先被呼叫,然後各個基類的解構函式被呼叫。這就是說,即使是抽象類,編譯器也要產生對~awov的呼叫,所以要保證為它提供函式體。如果不這麼做,連結器就會檢測出來,最後還是得回去把它添上。

雖然抽象類的解構函式可以是純虛擬函式,但要例項化其派生類物件,仍必須提供抽象基類中解構函式的函式體。

抽象類的純虛擬函式的實現可以由自身給出,也可以由派生類給出。錯了,除了解構函式外,其他函式都不行,必須要在派生類中進行實現。

class a 

public: 
virtual ~a()=0; 
}; 

class b:public a 

public: 
virtual ~b(){}; 
}; 

int main() 

b bb; 
return 1; 
解構函式是純虛擬函式的亦為抽象類。 
上面的例子所以錯誤,因為b繼承a後沒有改寫a的純虛擬函式,因此b也是抽象類,自然不能例項化。 


修改如下則正確: 
class a 

public: 
virtual ~a()=0; 
}; 

class b:public a 

public: 
virtual ~b(){}; 
}; 

a::~a(){};//改寫a的純虛擬函式,此時a仍為抽象類 

int main() 

b bb; 
return 1; 

注意此時a仍為抽象類不能例項化,a aa則錯誤。