C++中構造函數和析構函數能否是虛函數

作者:billy
版權聲明:著作權歸作者所有,商業轉載請聯繫作者獲得授權,非商業轉載請註明出處

前言

在C++的類中,當我們用到多態的時候會把基類中的某個函數定義爲虛函數,然後在子類中重新實現這個函數。在此過程中我們引發了一個討論,基類中的構造函數和析構函數是否也可以定義爲虛函數呢?下面我們一起來分析一下。

構造函數

首先我們來看一下構造函數的定義:
類的構造函數是類的一種特殊的成員函數,它會在每次創建類的新對象時執行。該類對象被創建時,編譯系統爲該對象分配內存空間,並自動調用該構造函數,由構造函數完成成員的初始化工作

由定義我們知道構造函數主要是爲了在創建對象時完成初始化工作,初始化可以從一下幾個方向來考慮:

  1. 存儲空間
    我們知道一旦在類中定義了虛函數就會有一個虛函數表 vtable,vtable 存儲於對象的內存空間中,通過虛指針 vptr來確認調用哪一個函數。
    如果構造函數是虛的,那麼就需要通過 vtable來調用,但是此時對象還未實例化,即內存空間還沒有,是無法找到vtable的;
  2. 實際使用
    虛函數主要用於在信息不全的情況下,能使重載的函數得到對應的調用。構造函數本身就是要初始化實例,那使用虛函數就沒有實際意義;
  3. 實際含義
    在調用構造函數時還不能確定對象的真實類型(因爲子類會調父類的構造函數),而且構造函數的作用是提供初始化,在對象生命期只執行一次,不是對象的動態行爲,沒有必要成爲虛函數;
  • 總結:構造函數不需要是虛函數,也不允許是虛函數,因爲創建一個對象時我們總是要明確指定對象的類型

析構函數

析構函數的定義:
類的析構函數是類的一種特殊的成員函數,它會在每次刪除所創建的對象時執行。析構函數通常用於釋放在構造函數或在生命期內獲得的資源(如動態分配的內存)。從廣義上講,析構函數的作用並不僅僅限於釋放資源方面,它可以執行任意操作,用來執行對象即將被撤銷之前程序員所期待的任何操作。

在使用多態的時候,編譯器總是根據類型來調用類成員函數。但是一個派生類的指針可以安全地轉化爲一個基類的指針。這樣刪除一個基類的指針的時候,C++不管這個指針指向一個基類對象還是一個派生類的對象,調用的都是基類的析構函數而不是派生類的。如果你依賴於派生類的析構函數的代碼來釋放資源,而沒有重載析構函數,那麼會有資源泄漏。

  • 總結: 析構函數可以爲虛函數,而且當使用基類指針或引用來調用子類時,最好將基類的析構函數聲明爲虛函數,否則可以存在內存泄露的問題
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章