1. 程式人生 > >對類的理解(c++)

對類的理解(c++)

介紹目錄:

1.類成員

1.1 成員函式

1.2 建構函式

1.2.1 對建構函式的理解

1.2.2成員初始化列表

 1.2.3必須使用成員初始化列表的幾種情況

1.2.4對於拷貝建構函式的引數是一個引用的理解

1.2.5對深拷貝和淺拷貝的理解

1.3解構函式

1.3.1 單繼承

1.3.2 多繼承

 1.4 操作符過載

1.4.1複製建構函式和賦值運算子的區別

2.成員函式的過載,覆蓋和隱藏

2.1成員函式的覆蓋

2.2成員函式的隱藏

 

1.類成員

1.1 成員函式

呼叫成員函式時,實際上是使用物件來呼叫的。每個成員函式(除static成員函式外)都有一個額外的,隱含的形參this.在呼叫成員函式時,形參this初始化為呼叫函式的物件的地址。

例如: void Point3d::translate(Point3d* const this,const Point3d &pt){

this->x+=pt.x;

this->y+=pt.y;

this->z+=pt.z;

}

1.2 建構函式

若使用編譯器自動生成的預設建構函式,則類中的每個成員,使用與初始化變數相同的規則來進行初始化。

a.類成員:執行該型別的預設建構函式來初始化。

b.內建或符合型別的成員的初始值依賴於物件的作用域:在區域性作用域中這些物件不被初始化。在全域性作用域中,他們被初始化為0。

1.2.1 對建構函式的理解

假定有一個NoDefault類,他沒有定義自己的預設建構函式,卻有一個接受string實參的建構函式。因為該類定義了一個建構函式,因此編譯器將不合成預設的建構函式,意味著:

1)具有NoDefault成員的每個類的每個建構函式,必須在成員初始化列表中通過傳遞一個初始的string值給NoDefault建構函式來顯示的初始化NoDefault成員。

2)編譯器將不會為具有NoDefault型別成員的類合成預設建構函式,如果需要提供預設建構函式,就必須顯示定義。並且預設的建構函式必須顯示的初始化NoDefault成員。

3)NoDefault型別不能用作動態分配陣列的元素型別。

4)NoDefault型別的靜態分配陣列必須為每個元素提供一個顯式的初始化式

5) 如果有一個儲存NoDefault物件的容器,例如vector,就不能使用接受容器大小而沒有同時提供一個元素初始化式的建構函式。

總結:如果定義了其他建構函式,提供一個預設建構函式總是對的。

1.2.2成員初始化列表

i是記憶體的垃圾數字,而j為0.

在c++中,成員變數的初始化順序與變數在型別中的申明順序相同,而與他們在建構函式中初始化列表的順序無關。

 1.2.3必須使用成員初始化列表的幾種情況

對於沒有預設建構函式的類型別的成員,以及const型別的成員變數和引用型別的成員變數,都必須在建構函式的初始化列表中進行初始化。

1.2.4對於拷貝建構函式的引數是一個引用的理解

如果拷貝建構函式中的引數不是一個引用,即形如:

CClass(const CClass c_class)

相當於採用傳值的方式,而此時會呼叫該類的拷貝建構函式,從而造成無窮遞迴的呼叫拷貝建構函式,因此拷貝建構函式的引數必須是一個引用。

1.2.5對深拷貝和淺拷貝的理解

淺拷貝:被複制物件的所有變數都含有與原來物件相同的值,而所有的對其他物件的引用仍然指向原來的物件。換言之,淺拷貝僅僅複製所考慮的物件,而不復制它所引用的物件。

深拷貝:被複制物件的所有變數都含有與原來物件相同的值,出去那些引用其他物件的變數。那些引用其他物件的變數將指向被複制過的新物件,而不再是原有的那些被引用的物件。換言之,深拷貝把要複製的物件所引用的物件都複製一遍。

1.3解構函式

不管類中是否定義了自己的解構函式,編譯器都自動執行類中非static資料成員的解構函式。

雖然建構函式不能定義為虛擬函式,但是解構函式可以定義為虛擬函式。一般來說如果類中定義了虛擬函式,解構函式也因該定義為虛解構函式,尤其是類中有申請的動態記憶體,需要清理和釋放的時候。

與複製建構函式和賦值操作符不同,無論類中是否定義了自己解構函式,都會建立和執行合成解構函式,如果類中定義了解構函式,則類中定義的解構函式執行完以後執行合成解構函式。

(拷貝建構函式採用的是系統自動生成的版本,沒有輸出)

1.3.1 單繼承

派生時,建構函式和解構函式是不能繼承的(複製建構函式和賦值操作符過載函式也不能繼承),為了對基類成員初始化,必須對派生類的建構函式和解構函式重新定義,並在派生類的建構函式的初始化列表中呼叫基類的建構函式。

當物件被刪除時,派生類的解構函式被執行,解構函式不能繼承,所以,在執行派生類的解構函式時,基類的解構函式被自動執行。(順序:先執行派生類的解構函式在執行基類的解構函式)

1.3.2 多繼承

多繼承時,派生類的建構函式初始化列表需要呼叫各個基類的建構函式。

此時建構函式初始化列表只能控制用於初始化基類的值,不能控制基類的構造次序,基類建構函式按照基類建構函式在類派生列表中出現的次序呼叫。

 

在虛繼承中,首先呼叫虛基類的建構函式,虛基類如果有多個,則虛基類建構函式的呼叫順序是此虛基類在當前類派生表中出現的順序,而不是他們在成員初始化列表中的順序。

 1.4 操作符過載

1.4.1複製建構函式和賦值運算子的區別

複製建構函式只在物件例項化是才會被呼叫,在複製建構函式呼叫期間,這個物件處於未決狀態,複製建構函式不返回任何值。而賦值操作符是在一個現存的物件被賦予新的值時被呼叫。有返回值。

c++中空類預設產生預設建構函式,解構函式,複製建構函式,賦值運算子過載函式,取址運算子過載函式,const取址運算子過載函式。

operator new 和operator delete  與c中malloc和 free對應,只負責分配和釋放空間。(new為new operator  是new運算子)

2.成員函式的過載,覆蓋和隱藏

只用在同一類中定義的同名函式才存在過載關係,主要特點是函式的引數型別和數目有所不同,但不能出現函式引數的型別和個數相同僅僅依靠返回值來區別函式。過載和成員函式是否為虛擬函式無關。

2.1成員函式的覆蓋

覆蓋是指在派生類中覆蓋基類中的同名函式,要求基類必須是虛擬函式且:

1)與基類的虛擬函式有相同的引數個數

2)與基類的虛擬函式有相同的引數型別

3)與基類的虛擬函式有相同的返回型別或者與基類的虛擬函式的相同,或者返回指標(或引用)。並且派生類虛擬函式所返回的指標(引用)型別是基類中被替換的虛擬函式所返回的指標(引用)型別的子型別(派生型別)。

2.2成員函式的隱藏

隱藏是在某些情況下,派生類中的函式遮蔽了基類中的同名函式,這些情況包括:

1)

2)