C 多繼承建構函式初始化列表呼叫順序

2021-07-25 12:11:03 字數 1211 閱讀 3955

class

b1 ;//定義基類b1

class

b2 ;//定義基類b2

class

b3 ;//定義基類b3

class

c: public

b2, 

public

b1, 

public

b3 ;//繼承類c

void

main() 

//主函式

執行結果:consb2 2 consb1 1consb3 * consb1 3 consb2 4 consb3 * consc

//先按照繼承順序:b2,b1,b3

//第一步:先繼承b2,在初始化列表裡找到b2(b),列印"constb22"

//第二步:再繼承b1,在初始化列表裡找到b1(a),列印"constb11"

//第三步:又繼承b3,在初始化列表裡找不到b3(x),則呼叫b3裡的預設建構函式b3(),列印"constb3 *" 

//再按照資料成員定義順序

:memberb1,memberb2, memberb3

//第四步:在初始化列表裡找到memberb1(c),初始化乙個b1物件,用c為引數,則呼叫b1的建構函式,列印"constb13" 

//第五步:在初始化列表裡找到memberb2(d),初始化乙個b2物件,用d為引數,則呼叫b2的建構函式,列印"constb24" 

//第六步:在初始化列表裡找不到memberb3(x),則呼叫b3裡的預設建構函式b3(),列印"constb3*" 

//最後完成本物件初始化的剩下部分,也就是c自己的建構函式的函式體:{m=e;cout<<"consc"<

//第七步:列印"consc"

回到你的主要問題:為什麼會有兩次b3*出現? 

第一次是由於繼承了b3,雖然在c的建構函式的初始化列表裡你沒看到b3(x)或者b3(),但並不代表b3的建構函式沒有在發揮作用。事實上,b3被隱性初始化了,因為b3的建構函式沒有引數,所以寫不寫b3()都無所謂,這裡恰好省略了。b1,b2則都是顯性初始化,因為它們都需要引數。第二次是因為c有資料成員memberb3,又一次,你沒有在c的建構函式的初始化列表裡看到你希望出現的memberb3(),很顯然,這又是一次隱性初始化。b3的建構函式再次被暗中呼叫。每一次b3的建構函式被呼叫,都會列印出「consb3*」。兩次被呼叫,自然列印兩次「consb3 *」。

初始化列表呼叫子類建構函式

includeusing namespace std class a a是父類 a int x a x 帶 引數的建構函式對a 初始化 void printa class b public a b 是子類 void printb int main 如果在子類的建構函式中需要初始化父類的private...

C 建構函式 ,初始化列表

c 中的類的建構函式 1.如果類中沒有定義建構函式,編譯器將生成乙個預設建構函式,這個預設建構函式會呼叫類中所有成員的預設建構函式,但不會對如int,double的基本資料型別做初始化 2.類中可以定義多個建構函式,但每個建構函式應該有不同的引數實現 3.預設建構函式必須定義的情況,當需要定義乙個物...

C 建構函式初始化列表

從概念上講,可以認為建構函式分兩個階段進行 1.初始化階段 2.普通的計算階段。計算階段由建構函式函式體中的所有語句組成 不管成員是否在建構函式初始化列表中顯示初始化,類型別的資料成員總是在初始化階段初始化。初始化發生在計算階段的開始之前。建議 使用建構函式初始化列表 注 必須對任何const或引用...