C++ 構造函數與析構函數

構造函數

無參數構造函數

若是建立一個類你沒有寫任何構造函數,則系統會自動生成默認的無參構造函數,函數爲空,什麼都不作 c++

只要你寫了一個其餘的某一種構造函數(非無參構造函數),系統就不會再自動生成這樣一個默認的構造函數,若是但願有一個這樣的無參構造函數,則須要本身顯示地寫出來安全

通常構造函數(也稱重載構造函數)

通常構造函數能夠有各類參數形式,一個類能夠有多個通常構造函數,前提是參數的個數或者類型不一樣(基於c++的重載函數原理)函數

複製構造函數(也稱爲拷貝構造函數)

主要應用於使用一個已存在的對象去初始化一個新對象,使新對象的屬性和該對象保持一致。設計

若用戶未定義拷貝構造函數,編譯器就自動提供一個默認的複製構造函數,其做用僅是簡單地複製類中的每一個數據成員;爲了安全起見,類設計者須要提供拷貝構造函數;指針

拷貝構造函數通常形式:code

類名(const 類名& 對象名)
形如:CComplex(const CComplex& srcObj)

在如下三種狀況下,拷貝構造函數將被調用;對象

  • 創建新對象

使用一個已存在對象num,初始化即將要被建立的新對象,能夠有如下兩種形式:繼承

CComplex num1(num); //形式1 
CComplex num2=num; //形式2
  • 函數形參爲類對象

在函數調用時須要將實參對象完整地傳遞給形參,系統將默認調用拷貝構造函數,創建一個實參的拷貝,這樣形參對象和實參對象將具備相同的屬性值;內存

須要注意的是,僅形參是按值傳遞時纔會進行對象拷貝,如果傳遞引用,不會進行對象拷貝資源

形如:
//按值傳遞,複製對象
static void TransByValue(CComplex obj)
//傳遞引用,不復制對象
static void TransByRefence(const CComplex& obj)
  • 函數返回值是類對象

當一個函數返回值是一個類對象時,在該函數返回調用處時,系統會將函數中的對象複製一份到別的地方,即便返回值沒有被使用;

形如:
static CComplex GetObj()
{
CComplex ret(10,10);
return ret;
}
轉換構造函數

轉換構造函數的做用是將一個其餘類型的數據轉換爲一個類的對象。轉換構造函數也是一種構造函數,它遵循構造函數的通常原則,咱們一般把僅有一個參數的構造函數用做類型轉換,所把它稱爲轉換構造函數。

轉換構造函數中的類型數據能夠是普通類型,也能夠是類類型,其通常形式以下:

類名(指定類型的數據)
C++ 構造函數後加冒號

冒號後的內容是初始化成員列表,通常有三種狀況:

  • 一、對含有對象成員的對象進行初始化,例如,

類line有兩個私有對象成員startpoint、endpoint,line的構造函數寫成:

line(int sx,int sy,int ex,int ey):startpoint(sx,sy),endpoint(ex,ey){……}

初始化時按照類定義中對象成員的順序分別調用各自對象的構造函數,再執行本身的構造函數

  • 二、對於不含對象成員的對象,初始化時也能夠套用上面的格式,例如,

類rectangle有兩個數據成員length、width,其構造函數寫成:

rectangle():length(1),width(2){}
rectangle(int x,int y):length(x),width(y){}
  • 三、對父類進行初始化,例如,

CDlgCalcDlg的父類是MFC類CDialog,其構造函數寫爲:

CDlgCalcDlg(CWnd\* pParent ): CDialog(CDlgCalcDlg::IDD, pParent)

其中IDD是一個枚舉元素,標誌對話框模板的ID

使用初始化成員列表對對象進行初始化,有時是必須的,有時是出於提升效率的考慮

淺拷貝與淺拷貝的區別:

在使用一個對象對另外一個對象初始化或賦值時,若對象包含指針成員變量,則須要手動的編寫拷貝構造函數實現深拷貝,調用編譯器的內部默認的拷貝構造函數則只能實現淺拷貝操做。

【淺拷貝】只是增長了一個指針,指向已存在對象的內存。

【深拷貝】是增長了一個指針,並新開闢了一塊空間,讓指針指向這塊新開闢的空間。

【淺拷貝】在多個對象指向一塊空間的時候,釋放一個空間會致使其餘對象所使用的空間也被釋放了,再次釋放便會出現錯誤

對象拷貝和對象賦值的區別

對象的賦值是對一個已經存在的對象進行從新賦值,所以必須先定義被賦值的對象,才能進行賦值;

對象的拷貝是在從無到有創建一個新對象,並使這個新對象和已有對象徹底相同;

例如:

CComlex num1(1,1);
CCompex num2(2,2);

//對象賦值 使對象num2的值和對象num1一致,調用進行operator=運算符重載
num2 = num1;

//對象拷貝,利用對象num2建立新對象num3;
CCompex num3 = num2;
派生類和基類構造和析構函數

1).在調用派生類構造函數以前,系統會先調用基類的構造函數;若是派生類構造函數列表中包含對基類子對象成員的初始化(如上例中的monitor),每一個基類子對象初始化時也要調用一次基類構造函數;最後纔是派生類調用自身的構造函數來初始化自身新增的成員(如上例中的age,addr)。執行順序就是派生類構造函數列表順序:

2).正如派生類不能繼承基類的構造函數,派生類也不能繼承基類的析構函數,派生類的清理工做由派生自身析構函數負責,基類的清理工做由基類析構函數負責。

析構函數的調用順序正好和構造函數調用順序相反,即先調用派生類析構函數清理新增的成員,再調用子對象析構函數(基類析構函數)清理子對象,最後再調用基類析構函數清理基類成員。

析構函數

當對象超出做用域或動態分配的對象被刪除時,將自動調用析構函數。

析構函數可用於釋放對象時構造或在對象的生命期中所獲取的資源。

無論類是否認義了本身的析構函數,編譯器都自動執行類中非static 數據成員的析構函數。

  • (1)、析構函數沒有返回值和參數列表
  • (2)、析構函數不能重載
  • (3)、析構函數由系統自動調用,不能顯式調用
  • (4)、析構函數能夠是inline函數
  • (5)、析構函數應該設置爲類的公有成員
  • (6)、每一個類有應該有一個析構函數,若是沒有顯式定義,那麼系統會自動生成一個默認的析構函數
相關文章
相關標籤/搜索