程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++ 初始化形式、變量初始化規則、類構造函數的初始化列表

C++ 初始化形式、變量初始化規則、類構造函數的初始化列表

編輯:關於C++

類構造函數的初始化列表,舉例
 

一個對象的構造分兩部分,首先是分配空間,然後初始化。

只要有對象生成,不管是以什麼形式生成,都會調用構造函數進行初始化。

然後下面有個例子,在藍色區域Big類的復制構造函數中,使用初始化列表進行成員的初始化(方法1)沒有問題,而如果不使用初始化列表、直接在函數裡用裡面注釋掉的代碼(方法2)則會報錯:Base類沒有合適的構造函數。

 

// W3-課程作業2-4.cpp : Defines the entry point for the console application.
#include "stdafx.h"
//下面程序的輸出結果是:
//5, 5
//5, 5
//請填空:

#include 
using namespace std;
class Base {
public:
	int k;
	Base(int n) :k(n) { }
};
class Big  {
public:
	int v; Base b;
	// 在此處補充你的代碼
	//Big ________________{}
	//Big ________________{}
	Big(int n) :v(n), b(n) {}
	
	Big(const Big& a) :v(a.v), b(a.b)
	{
		//v = a.v;
		//b = a.b;
	}
};

int _tmain(int argc, _TCHAR* argv[])
{
	Big a1(5);    
	Big a2 = a1;
	cout << a1.v << "," << a1.b.k << endl;
	cout << a2.v << "," << a2.b.k << endl;
	system("pause");
	return 0;
}
錯誤的原因如下。

 

構造一個對象時,先要構造這個對象的每一個屬性,然後再執行該對象構造函數內部的語句。
初始化列表,其實是定義了如何構造每個屬性。而初始化列表中沒有列出的屬性值,則是按照默認的方法初始化。
因此,對於這個例子而言:
方法1使用初始化列表:采用初始化列表中的b(a.b)構造Base類對象b,即調用了合成的復制構造函數,沒有問題;
方法2不使用初始化列表:由於b的構造方法並沒有在初始化列表中說明,因此在執行構造函數之前,需要先調用無參構造函數產生一個Base對象b,而這個無參構造函數並不存在,從而產生錯誤。

另外,之前以為方法2那樣,執行b=a.b;時會調用合成的復制構造函數(即使是這樣,b也還是沒有合適的構造函數初始化。這條語句的時候已經是賦值,而不是初始化),事實上這句是賦值,調用的當然不是復制構造函數,而是執行合成賦值操作符(與合成復制構造函數類似)。這裡把概念弄清楚,以後會少犯混的。

 

事實上,調用復制構造函數有三種情形:(而且復制構造函數本身是構造函數的一種,用來對對象初始化)

定義一個新對象,並用一個同類型的對象對它進行初始化時(顯示使用復制構造函數)當將該類型的對象傳遞給函數,即給形參初始化(隱式使用復制構造函數)當從函數返回該類型的對象時,即給返回值對象初始化(隱式使用復制構造函數)(另)初始化順序容器中的元素(另)根據元素初始化式列表初始化數組元素

派生類對象生成時,要先調用基類的構造函數。有兩種方式調用:

 

 

顯示方式。即在初始化列表中,指明 成員基類對象(基類對象) 這樣的方式調用基類的構造函數隱式方式。即不指明,自動得調用基類的默認構造函數。(你要確保基類有默認構造函數,否則出錯)

初始化列表
 

 

必須對任何 const 或引用類型成員、以及沒有默認構造函數的類類型的成員使用初始化列表。
(記住,可以初始化const對象或引用類型的對象,但不能對它們賦值。在開始執行構造函數的函數體之前,要完成初始化。
初始化const或引用類型數據成員的唯一機會是在構造函數初始化列表中。)

 

成員初始化的次序
 

成員被初始化的次序就是聲明成員的次序。與構造函數初始化列表無關。(消亡順序和聲明順序相反,忘了哪看的了。)
 

 

C++ 支持兩種形式的初始化

復制初始化。用等號。直接初始化。把初始化式放在括號中。 初始化不是賦值。初始化指創建變量並給它賦初始值,而賦值則是擦除對象的當前值並用新值代替。

 

當用於類類型對象時,初始化的復制形式和直接形式有所不同。直接初始化直接調用與實參匹配的構造函數,復制初始化總是調用復制構造函數。復制初始化首先使用指定構造函數創建一個臨時對象,然後用復制構造函數將那個臨時對象復制到正在創建的對象。所以,直接初始化效率高些。
 

變量初始化規則

 

內置類型變量的初始化 全局變量初始化為0,局部變量初始化不進行自動初始化,我覺得靜態變量應該也是初始化為0
類類型變量的初始化

C++ 區分了聲明和定義
 

 

定義,用於為變量分配存儲空間,還可以為變量指定初始值。變量有且僅有一次定義。

聲明,用於向程序表明變量的類型和名字(標識符)。變量可以聲明多次。
定義也是聲明,當定義變量時我們聲明了它的類型和名字。
可以通過使用extern關鍵字聲明變量而不定義它。extern聲明不是定義,也不分配存儲空間,它只是說明變量定義在程序的其他地方(文件)。

只有當聲明也是定義時,聲明才可以有初始化式,因為只有定義才分配存儲空間。初始化式必須要有存儲空間來進行初始化。如果聲明有初始化式,那麼它可被當作是定義,即使聲明標記為extern。

且只有當extern聲明位於函數外部時,才可以含有初始化式。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved