天天看點

從Qt談到C++(二):繼承時的含參基類與初始化清單提出疑問C++繼承與構造函數初始化清單

當我們建立一個qt的圖形界面的工程時,我們可以看看它自動生成的架構代碼,比如我們的主視窗名稱為mainwindow,我們來看看mainwindow.cpp檔案:

不同于一般的繼承,這裡的父類的括号裡帶有參數,我們通常都使用過不帶參數,甚至不帶括号的基類名稱。這裡的基類為什麼帶着參數呢?

c++中類的繼承與java中的不同,c++的派生類不能繼承父類的構造函數和析構函數,隻能繼承父類的公有成員。是以這就會造成一種結果——我們無法使用基類的構造函數來對子類進行初始化!

這裡我假設大家都有java的背景知識,沒有也沒關系,請聽我講。在java中我們可以使用關鍵字super來直接調用父類的構造函數。比如我們定義兩個類:rectangle (矩形),square (正方形)。從數學角度講,正方形是一種特殊的矩形,是以我們的square類繼承自rectangle類。在java中像這樣:

在派生類square的構造函數中我們使用了,super這一關鍵字,它會預設調用基類的構造函數來初始化派生類。是以它相當于用一個整型x來初始化長方形的長和寬,是以我們得到的是一個正方形。可以驗證一下,我們再使用一個類來驗證這個square是否可用,關鍵代碼如下:

列印結果就是  the area is 16

先依樣畫葫蘆,寫個c++版rectangle:

派生類的聲明部分,我們也可以實作;

這隻是聲明了square的構造函數,但是我們該如何實作呢?我們的c++可是沒有super這一關鍵字的,而且c++派生類不會繼承基類的構造函數。

有人說我可不可以這樣:

答案當然是 no!!。為了解決這一沖突,c++提供了繼承含參基類的實作方法,實作構造函數的方法就是這樣:

看懂沒有,不要奇怪這個空函數體,我們所需要的初始化操作已經完成。在main函數中試試:

注意在聲明部分就是和普通的繼承聲明是一樣的,基類也不用加參。

by the way,講一下一個類的構造過程。

首先,它的基類(如果有)的構造函數被調用。

然後,它的成員的構造函數被調用(如果有)。

最後,它自己的構造函數被調用。

當然了,這是題外話。

我們再回過頭來看看,最初的那段qt代碼:

現在,前面的 qmainwindow(parent) 這部分我們剛才講完了。接下來看看後面的

其實這就是構造函數的初始化清單。其實了解起來要容易的多。我們的類mainwindow有一個成員ui,它是mainwindow類型(這裡ui的類型和它所處的類是相同的,這是特殊的情況,我們不用計較)。舉個更一般的例子。

還記得我們剛才的矩形麼?我們可以使用這種方法來初始化它。

效果等價于剛才的:

明白了吧,但是其實兩種有點不同,那就是系統先調用初始化清單來初始化,接着會調用構造函數體内部的代碼來初始化,也就是說,後者會覆寫掉前者。

然後main函數中:

它的輸出結果 是 the area is 48

繼續閱讀