分清繼承關(guān)系中基類和子類構(gòu)造函數(shù)調(diào)用順序
我們這里將分析一下繼承關(guān)系中基類和子類構(gòu)造函數(shù)調(diào)用順序,希望通過本文,能使大家對于繼承的理解更加深刻。
首先回顧并討論先有雞還是先有蛋的問題在C++中將會是什么情況。如果編寫:
- class Egg;
- class Hen
- {
- public:
- int n;
- Egg egg;
- Hen() {
- n=5;
- cout<<"Hen's con "<
- }
- };
- class Egg : public Hen
- {
- public:
- int m;
- Egg(){
- m=10;
- cout<<"Egg's con"<
- }
- };
- int main()
- {
- Egg dan;
- }
這在C++中是無法編譯通過的,首先,學(xué)過編譯原理的都應(yīng)該知道,所有語言在編譯的時候都需要確定一個類的大小。C++的編譯器在編譯一個類的時候,需要分析這個類的大小,而sizeof(Egg)=sizeof(Hen)+sizeof(Egg)+…,編譯器無法獲知其大小,自然也無法編譯通過;而JAVA、C#則不同,其類的成員皆為基本類型或引用。同時,和Java、C#等語言不同,C++不能做全局優(yōu)化編譯(即使打開全局優(yōu)化開關(guān)也沒有用),它的編譯是逐步向后的分析方式。C++這樣做,也在編譯時就防止出現(xiàn)先有雞還是先有蛋而產(chǎn)生的矛盾。大家可以嘗試在C++中嘗試其他方法看編譯是否能夠通過。
JAVA雖然可以在Hen類的初始化時對Egg進行構(gòu)造(通過new Egg()),但運行時會出現(xiàn)堆棧溢出的錯誤:
- Exception in thread "main" java.lang.StackOverflowError
- at Egg.(…)
- at Hen.(…)
- at Egg.(…)
- at Hen.(…)
- …
下面回到本文的主題。我們知道,C++和JAVA不一樣,C++子類是默認(rèn)調(diào)用基類構(gòu)造函數(shù)的,而JAVA則需要super()。為了研究基類和子類構(gòu)造函數(shù)的調(diào)用順序問題,以上述程序為基礎(chǔ),我編寫了這樣一個測試:
- class Hen
- {
- public:
- int n;
- Hen() {
- n=5;
- cout<<"Hen's con "<
- }
- Hen(int i) {
- n=i;
- cout<<"Hen's con "<
- }
- };
- class Hen1
- {
- public:
- int x;
- Hen1() {
- x=6;
- cout<<"Hen1's con "<
- }
- };
- class Hen2
- {
- public:
- int y;
- Hen2() {
- y=7;
- cout<<"Hen2's con "<
- }
- };
- class Egg : public Hen, public Hen2, public Hen1
- {
- public:
- int m;
- Hen hen;
- Hen1 hen1;
- Hen2 hen2;
- Egg(int i) : Hen2(),Hen1(),Hen(),hen(i), hen2(), hen1(){
- m=10;
- cout<<"Egg's con"<
- }
- };
- int main()
- {
- Egg dan(1);
- }
- Output:
- Hen's con 5
- Hen2's con 7
- Hen1's con 6
- Hen's con 1
- Hen1's con 6
- Hen2's con 7
- Egg's con
通過這段程序可得如下結(jié)論:
1、基類構(gòu)造函數(shù)。如果有多個基類,則構(gòu)造函數(shù)的調(diào)用順序是某類在類繼承表中出現(xiàn)的順序,而不是它們在成員初始化表中的順序。如這里,是按照“class Egg : public Hen, public Hen2, public Hen1”的順序
2、成員類對象構(gòu)造函數(shù)。如果有多個成員類對象,則構(gòu)造函數(shù)的調(diào)用順序是對象在類中被聲明的順序,而不是它們出現(xiàn)在成員初始化表中的順序。如這里,是按照Egg聲明里
Hen hen;
Hen1 hen1;
Hen2 hen2;
的順序。
總1、2而言之,成員初始化表順序?qū)τ跇?gòu)造和賦值順序沒有任何意義
3、成員類對象并不是一開始就被構(gòu)造,再根據(jù)初始化表賦值,而是在調(diào)用構(gòu)造函數(shù)的時候,根據(jù)傳入的參數(shù)根據(jù)成員初始化表中進行一次構(gòu)造,構(gòu)造順序是對象在類中聲明的順序。
【編輯推薦】