C/C++基礎 -- 構造函數 constructor

  • 1、什麼是構造函數
  • 2、構造函數的定義
  • 2.1、定義構造函數
  • 2.2、關於構造函數的説明
  • 2.3、構造函數初始化列表
  • 3、構造函數的重載
  • 4、帶默認參數的構造函數
  • 關於構造函數默認參數的説明


本博文由 西北工業大學MOOC 總結而來,以備以後回顧。(侵刪)

1、什麼是構造函數

  我們在建立一個對象時,通常需要立即對這個對象進行初始化,如對數據成員的賦值操作。
  構造函數的作用就是在創建對象時初始化對象,進行為對象數據成員賦值等操作。

  為什麼需要構造函數進行初始化?

  1、因為類的數據成員不能再類定義時初始化,如下:

cJSON_CreateStringArray的使用_#構造函數


  類定義時並沒有產生實體對象,只是給出了類所有的數據成員類型,其不佔用存儲空間,因而也無法容納數據。

  2、如果一個類所有的數據成員是公有的,則可以在定義對象時對數據成員進行初始化,例如:

cJSON_CreateStringArray的使用_#構造函數_02


  但是如果類中的數據成員是私有的,如為private的或protected的,就不能從外部對其進行初始化,因為外部不能直接訪問私有的數據成員。

  所以,在這種情況下,我們就需要利用構造函數對所定義的對象進行初始化。

2、構造函數的定義

  C++提供了構造函數(constructor)來對對象進行初始化。構造函數時類的異種特殊成員函數,不需要認為調用,而是在建立對象時自動被執行。所以我們可以在構造函數中執行對象的初始化操作

2.1、定義構造函數

  C++規定,構造函數的名字和類名相同,並且不能指定返回類型。定義形式如下:

cJSON_CreateStringArray的使用_初始化_03

cJSON_CreateStringArray的使用_#c/c++_04


  與其他函數一樣,構造函數可以聲明為內聯的。

  只要創建類類型的新對象,都要執行構造函數,因此,構造函數的主要用途就是初始化類的數據成員。

cJSON_CreateStringArray的使用_#構造函數的重載_05


舉個栗子:

#include <iostream>
using namespace std;

class Cuboid	//定義Cuboid類表示長方體
{
public:
	Cuboid(int l, int h, int d);//帶參數的構造函數 -- 構造函數與類名相同
	int volumn() { return length*height*depth; }//計算長方體的體積
private:
	int length, heignt, depth;//長,高,深
}

Cuboid::Cuboid(int l, int h, int d)//在外部定義構造函數
{
	length=l, height=h, depth=d;//構造函數中初始化數據成員
	cout << "Cuboid: " << "L, H, D: " << l <<"," << h << "," << d << endl;
	//打印參數
}
int main()
{
	Cuboid A(1,2,3);//定義長方體對象A,調用構造函數初始化
	cout<<"column=" << a.volumn() << endl;//輸出體積
}

2.2、關於構造函數的説明

  1. 構造函數在創建對象時自動執行,而且只執行一次,並先於其他成員函數執行
  2. 構造函數一般聲明為公有的,因為創建對象通常在類的外部進行。
  3. 在構造函數的函數體中不僅可以對數據成員進行初始化,而且可以包含任意其他功能的語句,如分配動態內存等,但一般不提倡在構造函數中加入與初始化無關的內容
  4. 每個構造函數應該為每個數據成員提供初始化,如果使用沒有定義的成員時錯誤的。
  5. 帶參數的構造函數中的形參,時在定義對象時有對應的實參給定的,用這種方法可以實現不同對象進行不同的初始化。需要注意,實參必須與構造函數的形參的個數、次序、類型一致。

2.3、構造函數初始化列表

  與普通函數一樣,構造函數具有函數名、形參列表、函數體。與其他函數不同的是,構造函數可以包含一個構造函數初始化列表,一般形式為

cJSON_CreateStringArray的使用_構造函數_06


  構造函數初始化列表只能出現在構造函數的定義中出現,而不是函數原型聲明中。

  從初始化角度來看,構造函數分為兩個階段執行:①初始化階段;②普通計算階段。初始化階段有構造函數初始化列表組成。計算階段有構造函數的所有語句組成,初始化階段先於普通計算階段。即:

cJSON_CreateStringArray的使用_#構造函數的重載_07


舉個栗子:

#include <iostream>
using namespace std;

class Cuboid	//定義Cuboid類表示長方體
{
public:
	Cuboid(int l, int h, int d);//帶參數的構造函數 -- 構造函數與類名相同
	int volumn() { return length*height*depth; }//計算長方體的體積
private:
	int length, heignt, depth;//長,高,深
}
//利用初始化列表初始化數據成員,只能出現在構造函數的定義中
Cuboid::Cuboid(int l, int h, int d):length(l), height(h),depth(d)
{
	cout << "Cuboid: " << "L, H, D: " << l <<"," << h << "," << d << endl;
	//打印參數
}

3、構造函數的重載

  一個類的構造函數允許被重載,即定義多個版本的構造函數,但要保證不同構造函數的形參列表是唯一的。一個類的構造函數數量是沒有限制的。一般地,不同的構造函數允許建立對象時用不同的方式來初始化數據成員

構造函數重載舉例:

cJSON_CreateStringArray的使用_#構造函數_08


  儘管一個類中可以包含多個構造函數,但是對於每一個對象來説,建立對象時只執行其中一個構造函數,並非每個構造函數都執行。

4、帶默認參數的構造函數

  構造函數的參數允許使用默認值。對類的設計者來説,使用默認參數可以減少代碼重複;對類的使用者來説,使用默認參數可以方便地用適當的參數進行初始化。

帶默認參數的構造函數舉例:

cJSON_CreateStringArray的使用_#c/c++_09

關於構造函數默認參數的説明

  1. 必須在類的內部指定構造函數的默認參數,不能在類的外部指定默認參數:
  2. 如果構造函數的全部參數都指定了默認值,則在定義對象時可以給出一個或者幾個實參,也可以不給出實參。但是這是就與無參數的構造函數出現了歧義:
  3. 在一個類中定義了帶默認參數的構造函數後,不能再定義與之有衝突的重載構造函數。