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