class m1 class m2
m2()
virtual void mf() {} virtual void mf() {}
} ; };
class c : public b1, public b2
m1 m1;
m2 m2;};
(1)編譯器會不會為c生成預設構造(default ctor)
編譯器只在需要時才會為乙個類生成def ctor。「需要時」指:
a.乙個類有虛函式
b.乙個類有虛基類
c.乙個類的基類有def ctor
d.乙個類的成員類有def ctor
在這裡,class c符合c,d兩個條件,編譯器會為它生成def ctor.
(2)預設構造的內容
編譯器生成的def ctor是這樣的
c::c()
a.按宣告順序構造基類
b.設定虛表指標
c.按宣告順序構造成員類
(3)對自定義建構函式的改造
對於b1,b2,m1,m2,已有建構函式,但編譯器會對其改造,加入一些**,完成必要的初始化工作。改造後的ctor如下:(以b1為例)
b1::b1()
a.設定虛表指標
b.如果使用者寫有**(如i=0),則執行這些**
(4)綜合(2),(3),建構函式完整**如下
t::t()
在使用者**執行前,基類與成員類已構造完畢,虛指標已設定。
所以c的構造順序是:b1-〉b2-〉虛指標設定-〉m1-〉m2->c自己的**(如果有的話)
由(3)可知,每個類的ctor中,都會暫時將虛指標指向自己的虛表。呼叫b1::b1時,虛指標指向b1的虛表,然後在c::c中,虛指標被重新設定為c的虛表。
在繼承體系中,構造是由上而下的,b1或b2構造時,c還未構造。c構造時,b1和b2已構造完成。
所以在繼承體系中,乙個類的建構函式執行時,該類的所有基類已構造完畢,虛指標已設定,所有成員類也已構造完畢。但該類的所有子類均未構造完成。
2.析構函式
(1)編譯器會不會為c生成析構函式(dtor)
編譯器只在需要時才會為乙個類生成dtor。「需要時」指:
a.類的基類有析構
b.類的成員類有析構
與構造不同,少了兩點,因為在乙個類析構時,這是乙個破壞操作(destory),既然類以已經沒用了,何必再把虛指標設一下呢。
(2)析構的內容
編譯器生成的析構是這樣的
c::~c()
a.按宣告順序相反的順序析構成員類
b.按宣告順序相反的順序析構基類
這裡的相反順序是c++標準規定的要求,不同編譯器都應做到,否則不符合標準(實際上編譯器或多或少都有不符標準的地方,當然不是指這裡所說的順序問題)
(3)完整的析構的呼叫順序
對於已有析構函式的類,編譯器會對其改造,加入一些**,完成必要的工作。改造後的dtor如下:
t::~t()
這是完整的析構的呼叫順序
在使用者**執行前,虛指標已重新設定,以便使用者**能正確執行。然後再析構成員類和基類。
所以,如果上面例子中的五個類都有析構函式的話,呼叫順序是:
虛指標設定-〉c自己的**->m2-〉m1-〉b2-〉b1
每個類的dtor中,都會暫時將虛指標指向自己的虛表。呼叫c::~c時,虛指標指向c的虛表,然後在b1::~b1中,虛指標被重新設定為b1的虛表。
可見,在繼承體系中,析構是由下而上的,b1或b2析構時,c已被析構。c析構時,b1和b2還未被析構。
所以在繼承體系中,乙個類的析構函式執行時,該類的所有基類還未被析構,所有成員類也未被析構。但該類的所有子類均已析構完成。
3.虛函式
在構造或析構中呼叫虛函式,會怎樣.如:
b1::b1()
呼叫的是b1::f()還是c::f()
答案是b1::f()
每個類的ctor中,都會暫時將虛指標指向自己的虛表。呼叫b1::b1時,虛指標指向b1的虛表
所以是b1::f()
如果在c的建構函式中呼叫f(),那就呼叫c::f()
c 繼承中的構造與析構
問題 如何初始化父類成員?父類與子類的建構函式的關係?在子類物件構造時,需要呼叫父類建構函式對其繼承得來的成員進行初始化。在子類物件析構時,需要呼叫父類析構函式對其繼承得來的成員進行清理。繼承中的構造與析構呼叫規則 1.子類物件在建立時會首先呼叫父類的建構函式 2.父類建構函式執行結束後,執行子類的...
C 繼承與構造析構
include 子類物件可以當作父類物件使用 子類物件可以直接賦值給父類物件 子類物件可以直接初始化父類物件 父類指標可以直接指向子類物件 父類引用可以直接引用子類物件 子類物件構造時,需要呼叫父類建構函式對其繼承得來的成員進行初始化 子類物件析構時,需要呼叫父類析構函式對其繼承得來的成員進行清理 ...
繼承中的構造與析構
賦值相容性原則 子類物件可以當作父類物件使用 子類物件可以直接賦值給父類物件 子類物件可以直接初始化父類物件 父類指標可以直接指向子類物件 父類引用可以直接引用子類物件 子類是就是特殊的父類!class child public parent int main int argc,char argv ...