C++三大继承构造函数的执行顺序详解
寫的挺好的,關(guān)于繼承和構(gòu)造函數(shù)的先后順序問題。
?
轉(zhuǎn)自:?http://blog.csdn.net/daheiantian/archive/2011/02/18/6438782.aspx?
?
一、單繼承
核心:在構(gòu)造子類之前一定要執(zhí)行父類的一個(gè)構(gòu)造函數(shù)。
1.構(gòu)造函數(shù)(不包括復(fù)制構(gòu)造函數(shù))。
????????順序:①直接父類;②自己??
????????????注意:若直接父類還有父類,那么“直接父類的父類”會(huì)在“直接父類” 之前 構(gòu)造。 可以理解為這是一個(gè)遞歸的過程,知道出現(xiàn)一個(gè)沒有父類的類才停止。
????2.1 如果沒有顯式定義構(gòu)造函數(shù),則“合成的默認(rèn)構(gòu)造函數(shù)”會(huì)自動(dòng)調(diào)用直接父類的“默認(rèn)構(gòu)造函數(shù)”,然后調(diào)用編譯器為自己自動(dòng)生成的“合成的默認(rèn)構(gòu)造函數(shù)”。?
????2.2 如果顯式定義了自己的構(gòu)造函數(shù)?
????????2.2.1 如果沒有顯式調(diào)用直接父類的任意一個(gè)構(gòu)造函數(shù),那么和“合成的默認(rèn)構(gòu)造函數(shù)”一樣,會(huì)先自動(dòng)調(diào)用直接父類的 默認(rèn)構(gòu)造函數(shù),然后調(diào)用自己的構(gòu)造函數(shù)。??
????????2.2.2 如果顯式調(diào)用了直接父類的任意一個(gè)構(gòu)造函數(shù),那么會(huì)先調(diào)用直接父類相應(yīng)的構(gòu)造函數(shù),然后調(diào)用自己的構(gòu)造函數(shù)。
2. 復(fù)制構(gòu)造函數(shù)
???????????順序:①直接父類;②自己?
???????????????注意:和構(gòu)造函數(shù)一樣,若直接父類還有父類,那么“直接父類的父類”會(huì)在“直接父類” 之前 構(gòu)造。 可以理解為這是一個(gè)遞歸的過程,知道出現(xiàn)一個(gè)沒有父類的類才停止。
????2.1 如果?沒有顯式定義復(fù)制構(gòu)造函數(shù),則“合成的復(fù)制構(gòu)造函數(shù)”會(huì)自動(dòng)調(diào)用直接父類的“復(fù)制構(gòu)造函數(shù)”,然后調(diào)用編譯器為自己自動(dòng)生成的“合成的復(fù)制構(gòu)造函數(shù)”(注意:不是默認(rèn)構(gòu)造函數(shù))??
????2.2 如果顯式定義了自己的復(fù)制構(gòu)造函數(shù) (和構(gòu)造函數(shù)類似)?
????????2.2.1 如果沒有顯式調(diào)用父類的任意一個(gè)構(gòu)造函數(shù),那么會(huì)先調(diào)用直接父類的 默認(rèn)構(gòu)造函數(shù)(注意:不是 復(fù)制構(gòu)造函數(shù))。?
????????2.2.2 如果顯式調(diào)用了直接父類的任意一個(gè)構(gòu)造函數(shù),那么會(huì)先調(diào)用直接父類相應(yīng)的構(gòu)造函數(shù)。
3.賦值操作符重載
????3.1 如果沒有顯式定義,會(huì)自動(dòng)調(diào)用直接父類的賦值操作符。(注意:不是 默認(rèn)構(gòu)造函數(shù))???
????3.2 如果顯式定義了,就只執(zhí)行自己定義的版本,不再自動(dòng)調(diào)用直接父類的賦值操作符,只執(zhí)行自己的賦值操作符。?
????????????注意:如有需要對(duì)父類子部分進(jìn)行賦值,應(yīng)該在自己編寫的代碼中,顯式調(diào)用父類的賦值操作符。?
4. 析構(gòu)函數(shù)??
????與構(gòu)造函數(shù) 順序相反。
二、多繼承
和單繼承的差別就是:需要考慮到多個(gè)直接父類。其它的都相同
1.構(gòu)造函數(shù)(不包括復(fù)制構(gòu)造函數(shù))。
???????????????順序:①所有直接父類;(按照基類繼承列表中聲明的順序)②自己??
????????????注意:若直接父類還有父類,那么“直接父類的父類”會(huì)在“直接父類” 之前 構(gòu)造。 可以理解為這是一個(gè)遞歸的過程,知道出現(xiàn)一個(gè)沒有父類的類才停止。
????2.1 如果?沒有 顯式定義構(gòu)造函數(shù),則“合成的默認(rèn)構(gòu)造函數(shù)”會(huì)自動(dòng)依次調(diào)用所有直接父類的“默認(rèn)構(gòu)造函數(shù)”,然后調(diào)用編譯器為自己自動(dòng)生成的“合成的默認(rèn)構(gòu)造函數(shù)”。?
????2.2 如果顯式定義了自己的構(gòu)造函數(shù)?
????????2.2.1 如果沒有顯式調(diào)用父類的任意一個(gè)構(gòu)造函數(shù),那么和“合成的默認(rèn)構(gòu)造函數(shù)”一樣,會(huì)自動(dòng)依次調(diào)用所有直接父類的 默認(rèn)構(gòu)造函數(shù),然后調(diào)用自己的構(gòu)造函數(shù)。?
????????2.2.2 如果顯式調(diào)用了父類的任意一個(gè)構(gòu)造函數(shù),那么按照基類列表的順序,對(duì)于每一個(gè)父類依次判斷:若顯式調(diào)用了構(gòu)造函數(shù),那么會(huì)調(diào)用該父類相應(yīng)的構(gòu)造函數(shù);如果沒有顯式調(diào)用,就調(diào)用默認(rèn)構(gòu)造函數(shù)。最后調(diào)用自己的構(gòu)造函數(shù)。
2. 復(fù)制構(gòu)造函數(shù)
???????????????順序:①所有直接父類;(按照基類繼承列表中聲明的順序)②自己??
????????????注意:和構(gòu)造函數(shù)一樣,若直接父類還有父類,那么“直接父類的父類”會(huì)在“直接父類” 之前 構(gòu)造。 可以理解為這是一個(gè)遞歸的過程,知道出現(xiàn)一個(gè)沒有父類的類才停止。
????2.1 如果?沒有顯式定義復(fù)制構(gòu)造函數(shù),則“合成的復(fù)制構(gòu)造函數(shù)”會(huì)自動(dòng)依次調(diào)用所有直接父類的“復(fù)制構(gòu)造函數(shù)”,然后調(diào)用編譯器為自己自動(dòng)生成的“合成的復(fù)制構(gòu)造函數(shù)”(注意:不是默認(rèn)構(gòu)造函數(shù))?
????2.2 如果顯式定義了自己的復(fù)制構(gòu)造函數(shù) (和構(gòu)造函數(shù)類似)?
????????2.2.1 如果沒有顯式調(diào)用父類的任意一個(gè)構(gòu)造函數(shù),那么會(huì)先自動(dòng)依次調(diào)用直接父類的 默認(rèn)構(gòu)造函數(shù)(注意:不是 復(fù)制構(gòu)造函數(shù))。?
????????2.2.2 如果顯式調(diào)用了直接父類的任意一個(gè)構(gòu)造函數(shù),那么按照基類列表的順序,對(duì)于每一個(gè)父類依次判斷:若顯式調(diào)用了構(gòu)造函數(shù),那么會(huì)調(diào)用該父類相應(yīng)的構(gòu)造函數(shù);如果沒有顯式調(diào)用,就調(diào)用默認(rèn)構(gòu)造函數(shù)。最后調(diào)用自己的復(fù)制構(gòu)造函數(shù)。
3.賦值操作符重載
????3.1 如果沒有顯式定義,會(huì)自動(dòng)依次調(diào)用直接父類的賦值操作符。(注意:不是 默認(rèn)構(gòu)造函數(shù))?
????3.2 如果顯式定義了,就只執(zhí)行自己定義的版本,不再自動(dòng)調(diào)用直接父類的賦值操作符,只執(zhí)行自己的賦值操作符。??
????????????注意:如有需要對(duì)父類子部分進(jìn)行賦值,應(yīng)該在自己編寫的代碼中,顯式調(diào)用所有直接父類的賦值操作符。?
4. 析構(gòu)函數(shù)??
????與 構(gòu)造函數(shù) 順序相反。
三、虛繼承
和多繼承的差別就是:要考慮到虛基類,其它的都相同。(虛基類的初始化要早于非虛基類,并且只能由子類對(duì)其進(jìn)行初始化)
1.構(gòu)造函數(shù)(不包括復(fù)制構(gòu)造函數(shù))。
????????????????????????????????順序:①所有虛基類(按照基類繼承列表中聲明的順序進(jìn)行查找);②所有直接父類;(按照基類繼承列表中聲明的順序)③自己??
????????????注意:若虛基類或者直接父類還有父類,那么“直接父類的父類”會(huì)在“直接父類” 之前 構(gòu)造,“虛基類的父類”也會(huì)在“虛基類”之前構(gòu)造。 可以理解為這是一個(gè)遞歸的過程,知道出現(xiàn)一個(gè)沒有父類的類才停止。
????2.1 如果?沒有 顯式定義構(gòu)造函數(shù),則“合成的默認(rèn)構(gòu)造函數(shù)”會(huì)先依次調(diào)用所有虛基類的默認(rèn)構(gòu)造函數(shù),然后再自動(dòng)依次調(diào)用所有直接父類的“默認(rèn)構(gòu)造函數(shù)”,最后調(diào)用編譯器為自己自動(dòng)生成的“合成的默認(rèn)構(gòu)造函數(shù)”。?
????2.2 如果顯式定義了自己的構(gòu)造函數(shù)?????????2.2.1 如果沒有顯式調(diào)用父類的任意一個(gè)構(gòu)造函數(shù),那么和“合成的默認(rèn)構(gòu)造函數(shù)”一樣,會(huì)先依次調(diào)用所有虛基類的默認(rèn)構(gòu)造函數(shù),然后再自動(dòng)依次調(diào)用所有直接父類的 默認(rèn)構(gòu)造函數(shù),最后調(diào)用自己的構(gòu)造函數(shù)。?
????????2.2.2 如果顯式調(diào)用了父類的任意一個(gè)構(gòu)造函數(shù),那么按照基類列表的順序,先初始化所有虛基類,再初始化所有直接父類。對(duì)于每一個(gè)父類依次判斷:若顯式調(diào)用了構(gòu)造函數(shù),那么會(huì)調(diào)用該父類相應(yīng)的構(gòu)造函數(shù);如果沒有顯式調(diào)用,就調(diào)用默認(rèn)構(gòu)造函數(shù)。最后調(diào)用自己的構(gòu)造函數(shù)。
2. 復(fù)制構(gòu)造函數(shù)
???????????????????????????????順序:①所有虛基類(按照基類繼承列表中聲明的順序進(jìn)行查找);②所有直接父類;(按照基類繼承列表中聲明的順序)③自己??
????????????注意:和構(gòu)造函數(shù)一樣,若虛基類或者直接父類還有父類,那么“直接父類的父類”會(huì)在“直接父類” 之前 構(gòu)造,“虛基類的父類”也會(huì)在“虛基類”之前構(gòu)造。 可以理解為這是一個(gè)遞歸的過程,知道出現(xiàn)一個(gè)沒有父類的類才停止。
????2.1 如果?沒有顯式定義復(fù)制構(gòu)造函數(shù),則“合成的復(fù)制構(gòu)造函數(shù)”會(huì)自動(dòng)依次調(diào)用所有直接父類的“復(fù)制構(gòu)造函數(shù)”,然后調(diào)用編譯器為自己自動(dòng)生成的“合成的復(fù)制構(gòu)造函數(shù)”(注意:不是默認(rèn)構(gòu)造函數(shù))?
????2.2 如果顯式定義了自己的復(fù)制構(gòu)造函數(shù) (和構(gòu)造函數(shù)類似)?
????????2.2.1 如果沒有顯式調(diào)用父類的任意一個(gè)構(gòu)造函數(shù),那么會(huì)先依次調(diào)用所有虛基類的默認(rèn)構(gòu)造函數(shù),然后再依次調(diào)用所有直接父類的 默認(rèn)構(gòu)造函數(shù)(注意:不是 復(fù)制構(gòu)造函數(shù))。?
????????2.2.2 如果顯式調(diào)用了直接父類的任意一個(gè)構(gòu)造函數(shù),那么按照基類列表的順序,先初始化所有虛基類,再初始化所有直接父類。對(duì)于每一個(gè)父類依次判斷:若顯式調(diào)用了構(gòu)造函數(shù),那么會(huì)調(diào)用該父類相應(yīng)的構(gòu)造函數(shù);如果沒有顯式調(diào)用,就調(diào)用默認(rèn)構(gòu)造函數(shù)。
3.賦值操作符重載
????3.1 如果沒有顯式定義,會(huì)自動(dòng)依次調(diào)用所有虛基類和所有直接父類的賦值操作符。(注意:不是 默認(rèn)構(gòu)造函數(shù))?
?????????????3.2 如果顯式定義了,就只執(zhí)行自己定義的版本,不再自動(dòng)調(diào)用直接父類的賦值操作符,只執(zhí)行自己的賦值操作符。??
????????????注意:如有需要對(duì)父類子部分進(jìn)行賦值,應(yīng)該在自己編寫的代碼中,顯式調(diào)用所有虛基類和所有直接父類的賦值操作符。?
4. 析構(gòu)函數(shù)??
????與 構(gòu)造函數(shù) 順序相反。
四、總結(jié):
1.?整體順序:虛基類??-->??直接父類??-->自己
2. 在任何顯式定義的構(gòu)造函數(shù)中,如果沒有顯式調(diào)用父類的構(gòu)造函數(shù),那么就會(huì)調(diào)用父類的默認(rèn)構(gòu)造函數(shù)。
3.?合成的復(fù)制構(gòu)造函數(shù)、合成的賦值操作符,(當(dāng)沒有顯式定義時(shí),編譯器自動(dòng)提供),會(huì)自動(dòng)調(diào)用的是虛基類和直接父類的復(fù)制構(gòu)造函數(shù)和賦值操作符,而不是默認(rèn)構(gòu)造函數(shù);
4. 自己顯式定義的復(fù)制構(gòu)造函數(shù),除非在初始化列表中顯示調(diào)用,否則只會(huì)調(diào)用虛基類和父類的默認(rèn)構(gòu)造函數(shù)。
5. 自己顯式定義的賦值操作符,除非顯式調(diào)用,否則只執(zhí)行自己的代碼。
6. 析構(gòu)函數(shù)的執(zhí)行順序與 構(gòu)造函數(shù) 相反。
總結(jié)
以上是生活随笔為你收集整理的C++三大继承构造函数的执行顺序详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: uvalive5090(三维凸包)
- 下一篇: s3c2440移植MQTT