C 建構函式詳解(複製建構函式)

2021-08-22 10:36:01 字數 3571 閱讀 7677

該類物件被建立時,編譯系統物件分配記憶體空間,並自動呼叫該建構函式,由建構函式完成成員的初始化工作,故:建構函式的作用:初始化物件的資料成員。

1 class complex 

2 18

19 // 一般建構函式(也稱過載建構函式)

20 // 一般建構函式可以有各種引數形式,乙個類可以有多個一般建構函式,前提是引數的個數或者型別不同(基於c++的過載函式原理)

21 // 例如:你還可以寫乙個 complex( int num)的建構函式出來

22 // 建立物件時根據傳入的引數不同呼叫不同的建構函式

23 complex(double real, double imag)

24

28

29 // 複製建構函式(也稱為拷貝建構函式)

30 // 複製構造函式引數為類物件本身的引用,用於根據乙個已存在的物件複製出乙個新的該類的物件,一般在函式中會將已存在物件的資料成員的值複製乙份到新建立的物件中

31 // 若沒有顯示的寫複製建構函式,則系統會預設建立乙個複製建構函式,但當類中有指標成員時,由系統預設建立該複製建構函式會存在風險,具體原因請查詢有關 「淺拷貝」 、「深拷貝」的文章論述

32 complex(const complex & c)

33

38

39 // 型別轉換建構函式,根據乙個指定的型別的物件建立乙個本類的物件

40 // 例如:下面將根據乙個double型別的物件建立了乙個complex物件

41 complex::complex(double r)

42

46

47 // 等號運算子過載

48 // 注意,這個類似複製建構函式,將=右邊的本類物件的值複製給等號左邊的物件,它不屬於建構函式,等號左右兩邊的物件必須已經被建立

49 // 若沒有顯示的寫=運算子過載,則系統也會建立乙個預設的=運算子過載,只做一些基本的拷貝工作

50 complex &operator=(const complex &rhs)

51

57

58 // 複製等號右邊的成員到左邊的物件中

59 this->m_real = rhs.m_real;

60 this->m_imag = rhs.m_imag;

61

62 // 把等號左邊的物件再次傳出

63 // 目的是為了支援連等 eg: a=b=c 系統首先執行 b=c

64 // 然後執行 a= ( b=c的返回值,這裡應該是複製c值後的b物件)

65 return *this;

66 }

67 };

下面使用上面定義的類物件來說明各個建構函式的用法:

1 void main()

2

參考:

幾個原則:

c++ primer p406 :複製建構函式是一種特殊的建構函式,具有單個形參,該形參(常用const修飾)是對該類型別的引用。當定義乙個新物件並用乙個同型別的物件對它進行初始化時,將顯示使用複製建構函式。當該型別的物件傳遞給函式或從函式返回該型別的物件時,將隱式呼叫複製建構函式。

c++支援兩種初始化形式:複製初始化(int a = 5;)和直接初始化(int a(5);)對於其他型別沒有什麼區別,對於類型別直接初始化直接呼叫實參匹配的建構函式,複製初始化總是呼叫複製建構函式,也就是說:

a x(2);  //直接初始化,呼叫建構函式

a y = x;  //複製初始化,呼叫複製建構函式

必須定義複製建構函式的情況:

只包含類型別成員或內建型別(但不是指標型別)成員的類,無須顯式地定義複製建構函式也可以複製;有的類有乙個資料成員是指標,或者是有成員表示在建構函式中分配的其他資源,這兩種情況下都必須定義複製建構函式。

什麼情況使用複製建構函式:

類的物件需要拷貝時,拷貝建構函式將會被呼叫。以下情況都會呼叫拷貝建構函式:

(1)乙個物件以值傳遞的方式傳入函式體

(2)乙個物件以值傳遞的方式從函式返回

(3)乙個物件需要通過另外乙個物件進行初始化。

深拷貝和淺拷貝:

所謂淺拷貝,指的是在物件複製時,只對物件中的資料成員進行簡單的賦值,預設拷貝建構函式執行的也是淺拷貝。在「深拷貝」的情況下,對於物件中動態成員,就不能僅僅簡單地賦值了,而應該重新動態分配空間

如果乙個類擁有資源,當這個類的物件發生複製過程的時候,資源重新分配,這個過程就是深拷貝

上面提到,如果沒有自定義複製建構函式,則系統會建立預設的複製建構函式,但系統建立的預設複製建構函式只會執行「淺拷貝」,即將被拷貝物件的資料成員的值一一賦值給新建立的物件,若該類的資料成員中有指標成員,則會使得新的物件的指標所指向的位址與被拷貝物件的指標所指向的位址相同,delete該指標時則會導致兩次重複delete而出錯。下面是示例:

1 #include 2 #include 3 class person 

4 18 }

19

20 // 系統建立的預設複製建構函式,只做位模式拷貝

21 person(person & p)

22

26

27 ~person( )

28

31

32 private :

33 char * m_pname;

34 };

35

36 void main( )

37 46

47

48 // 下面自己設計複製建構函式,實現「深拷貝」,即不讓指標指向同一位址,而是重新申請一塊記憶體給新的物件的指標資料成員

49 person(person & chs);

50 59

60 // 則新建立的物件的m_pname與原物件chs的m_pname不再指向同一位址了

61 }

過載賦值操作符:

通過定義operate=的函式,可以對賦值進行定義。像其他任何函式一樣,操作符函式有乙個返回值和形參表。形參表必須具有與該操作符運算元書目相同的形參(如果操作符是乙個成員,則包括隱式this形參)。賦值是二元運算,所以該操作符函式有兩個形參:第乙個形參(隱含的this指標)對應著左運算元,第二個形參對應右運算元。

乙個應用了對賦值號過載的拷貝建構函式的例子:

1 #include 2 

3 using namespace std;

4 5 class a

6 ;15 16 a::a(int p)

17 21

22 a::a(const a &b)

23 {

24 *this = b;

25 cout<

C 建構函式詳解(複製建構函式)

該類物件被建立時,編譯系統物件分配記憶體空間,並自動呼叫該建構函式,由建構函式完成成員的初始化工作,故 建構函式的作用 初始化物件的資料成員。class complex 一般建構函式 也稱過載建構函式 一般建構函式可以有各種引數形式,乙個類可以有多個一般建構函式,前提是引數的個數或者型別不同 基於c...

C 建構函式 複製建構函式詳解

建構函式 成員函式的一種,名字與類相同,可以有引數,不能有返回值 void也不行 作用 對物件進行初始化,如給成員變數賦值。物件生成時,建構函式自動被呼叫,物件一旦生成,就再也不能再其上執行建構函式。乙個類可以有多個建構函式。為什麼需要建構函式?有了建構函式就不必專門再寫初始化函式,物件沒有被初始化...

C 建構函式詳解(複製建構函式)

該類物件被建立時,編譯系統物件分配記憶體空間,並自動呼叫該建構函式,由建構函式完成成員的初始化工作,故 建構函式的作用 初始化物件的資料成員。1 class complex 2 1819 一般建構函式 也稱過載建構函式 20 一般建構函式可以有各種引數形式,乙個類可以有多個一般建構函式,前提是引數的...