C 類(持續更新中。。。)

2021-08-04 20:12:11 字數 2446 閱讀 7539

假定csomething是乙個類,執行下面這些語句之後,記憶體裡建立了__6__個csomething物件。 1

2

3

4

5

6

7

csomething a();

csomething b(2);

csomething c[3];

csomething &ra = b;

csomething d=b;

csomething *pa = c;

csomething *p =newcsomething(4);

csomething a();// 沒有建立物件,這裡不是使用預設建構函式,而是定義了乙個函式;

csomething b(2);//使用乙個引數的建構函式,建立了乙個物件。

csomething c[3];//使用無參建構函式,建立了3個物件。

csomething &ra=b;//ra引用b,沒有建立新物件。

csomething d=b;//使用拷貝建構函式,建立了乙個新的物件d。

csomething *pa = c;//建立指標,指向物件c,沒有構造新物件。

csomething *p = new csomething(4);//新建乙個物件。

建構函式不能宣告為虛函式,析構函式可以宣告為虛函式,而且有時是必須宣告為虛函式。不建議在建構函式和析構函式裡面呼叫虛函式。靜態成員函式不能是虛函式;內聯函式不能為虛函式;

(1)從儲存空間角度

虛函式對應乙個vtable,這大家都知道,可是這個vtable其實是儲存在物件的記憶體空間的。問題出來了,如果建構函式是虛的,就需要通過 vtable來呼叫,可是物件還沒有例項化,也就是記憶體空間還沒有,無法找到vtable,所以建構函式不能是虛函式。

(2)從使用角度

(3)從實現上看

vbtl在構造函式呼叫後才建立,因而建構函式不可能成為虛函式  

虛函式的意思就是開啟動態繫結,程式會根據物件的動態型別來選擇要呼叫的方法。然而在建構函式執行的時候,這個物件的動態型別還不完整,沒有辦法確定它到底是什麼型別,故建構函式不能動態繫結。(動態繫結是根據物件的動態型別而不是函式名,在呼叫建構函式之前,這個物件根本就不存在,它怎麼動態繫結?) 

在類的繼承中,如果有基類指標指向派生類,那麼用基類指標delete時,如果不定義成虛函式,派生類中派生的那部分無法析構。

note: 

1. 如果我們定義了乙個建構函式,編譯器就不會再為我們生成預設建構函式了。

2. 編譯器生成的析構函式是非虛的,除非是乙個子類,其父類有個虛析構,此時的函式虛特性來自父類。

3. 有虛函式的類,幾乎可以確定要有個虛析構函式。

4. 如果乙個類不可能是基類就不要申明析構函式為虛函式,虛函式是要耗費空間的。

5. 析構函式的異常退出會導致析構不完全,從而有記憶體洩露。最好是提供乙個管理類,在管理類中提供乙個方法來析構,呼叫者再根據這個方法的結果決定下一步的操作。

6. 在建構函式不要呼叫虛函式。在基類構造的時候,虛函式是非虛,不會走到派生類中,既是採用的靜態繫結。顯然的是:當我們構造乙個子類的物件時,先呼叫基類的建構函式,構造子類中基類部分,子類還沒有構造,還沒有初始化,如果在基類的構造中呼叫虛函式,如果可以的話就是呼叫乙個還沒有被初始化的物件,那是很危險的,所以c++中是不可以在構造父類物件部分的時候呼叫子類的虛函式實現。但是不是說你不可以那麼寫程式,你這麼寫,編譯器也不會報錯。只是你如果這麼寫的話編譯器不會給你呼叫子類的實現,而是還是呼叫基類的實現。

7. 在 析構函式中 也不要呼叫虛函式。在析構的時候會首先呼叫子類的析構函式,析構掉物件中的子類部分,然後在呼叫基類的析構函式析構基類部分,如果在基類的析構函式裡面呼叫虛函式,會導致其呼叫已經析構了的子類物件裡面的函式,這是非常危險的。 

8. 記得在寫派生類的拷貝函式時,呼叫基類的拷貝函式拷貝基類的部分,不能忘記了。

c++中派生類在構造時會先呼叫基類的建構函式再呼叫派生類的建構函式,析構時則相反,先呼叫派生類的析構函式再呼叫基類的建構函式。假設乙個派生類的物件進行析構,首先呼叫了派生類的析構,然後在呼叫基類的析構時,遇到了乙個虛函式,這個時候有兩種選擇:plan a是編譯器呼叫這個虛函式的基類版本,那麼虛函式則失去了執行時呼叫正確版本的意義;plan b是編譯器呼叫這個虛函式的派生類版本,但是此時物件的派生類部分已經完成析構,「資料成員就被視為未定義的值」,這個函式呼叫會導致未知行為。實際情況中編譯器使用的是plan a,如果虛函式的基類版本不是純虛實現,不會有嚴重錯誤發生,但你依然會困惑虛函式機制失效,所以建議不要這麼幹。

c 中string類的使用(持續更新)

ps string中雖然有push back 但是沒有push front 它不能使用前面插入迭代器 1.將整形轉為string型別 include include using namespace std intmain 2.將string 轉為int型 使用stoi,atoi include in...

array工具類,持續更新中,,,

1.陣列去重 function uniquearray arr return temp or return array.from new set arr 2.計算陣列中值的出現次數 const countoccurrences arr,value arr.reduce a,v v value a 1...

底層工具類,date方法,持續更新中

1.剩餘時間格式化 剩餘時間格式化 export param times 傳入毫秒 param format h f s 大寫自動補全十位 returns string 小於10時,轉化為01,02等 export function formatnum n n export function for...