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