C++知識點49——類繼承與類的構造、拷貝、operator=和解構函式
一、類繼承與建構函式
在C++中,無論類是否有繼承關係,每個類各自控制它自己的成員的初始化。子類雖然含有基類的成員,但是並不能對基類的成員直接初始化,需要使用基類的建構函式初始化子類中的基類部分。
從語法上說,可以在子類的建構函式的函式體中給基類的protected或public成員賦值,但是最好不要這樣做
子類初始化時,會先呼叫基類的建構函式,初始化基類的部分並,然後按照子類成員在類中的宣告順序逐個初始化子類部分
示例
class base
{
public:
base():
bpub(0),
bpro(0),
bpri(0)
{
cout<<__func__<<endl;
}
base(int init):
bpub(0),
bpro(0),
bpri(0)
{
cout<<"base(int init)"<<endl;
}
~base(){cout<<__func__<<endl;}
int bpub;
protected:
int bpro;
private:
int bpri;
};
class derive:public base
{
public:
derive(){cout<<__func__<<endl;}
~derive(){cout<<__func__<<endl;}
int dpub;
protected:
int dpro;
private:
int dpri;
};
class derive2:public base
{
public:
derive2():
base(),
d2pub(-1),
d2pro(-1),
d2pri(-1)
{
cout<<__func__<<endl;
}
derive2(int init):
base(init),
d2pub(-1),
d2pro(-1),
d2pri(-1)
{
cout<<"derive2(int init)"<<endl;
}
~derive2()
{
cout<<__func__<<endl;
}
int d2pub;
protected:
int d2pro;
private:
int d2pri;
};
int main(int argc, char const *argv[])
{
derive d;
derive2 d21;
derive2 d22(10);
return 0;
}
上述程式碼演示瞭如何在子類的建構函式中顯示指定要呼叫基類的建構函式
輸出結果表示:
1、就算在子類的建構函式中不顯式指定呼叫基類的建構函式,當建立子類物件(derive)時,會先呼叫基類的預設建構函式並對基類部分進行預設初始化。
2、定義類時,可以將子類建構函式的形參傳給基類的建構函式
二、類繼承與拷貝建構函式
如果想在拷貝子類物件時,對基類的成員也進行拷貝,需要在子類的拷貝建構函式的初始化列表中顯示呼叫基類的拷貝建構函式。如果不顯示定義基類的拷貝建構函式,那麼在對子類進行拷貝構造操作時,會先呼叫基類的建構函式
示例
class base2
{
public:
base2(){cout<<__func__<<endl;}
base2(const base2 &b2):memb(b2.memb){cout<<"base2(const base2 &b2)"<<endl;}
~base2(){cout<<__func__<<endl;}
int memb;
};
class derive2:public base2
{
public:
derive2(){cout<<__func__<<endl;}
~derive2(){cout<<__func__<<endl;}
derive2(const derive2 &d2)
:base2(d2), memd(d2.memd) {cout<<"derive2(const derive2 &d2)"<<endl;}
int memd;
};
int main(int argc, char const *argv[])
{
derive2 d2;
derive2 b2t=d2;
return 0;
}
如果想在拷貝子類物件時,對基類的成員也進行拷貝,需要在子類的拷貝建構函式的初始化列表中顯示呼叫基類的拷貝建構函式。這樣,當對一個子類進行拷貝初始化時,也會先呼叫基類的拷貝建構函式,對子類中的基類部分進行拷貝初始化,然後再呼叫子類的拷貝建構函式進行對子類部分進行拷貝初始化
如果不顯示定義基類的拷貝建構函式,那麼在對子類進行拷貝構造操作時,會先呼叫基類的建構函式,將上述程式碼中的第5行註釋掉的輸出結果如下
所以,如果要定義子類的拷貝建構函式,請在子類的拷貝建構函式的初始化列表中顯示呼叫基類的拷貝建構函式,然後再對子類的成員進行初始化
三、類繼承與operator=
和拷貝建構函式一樣,子類的operator=必須顯示呼叫基類的operator=
示例
在拷貝建構函式的示例程式碼中分別新增基類和子類的operator=
class base2
{
public:
//....
base2 &operator=(const base2 &b2)
{
memb=b2.memb;
return *this;
}
int memb;
};
class derive2:public base2
{
public:
//....
derive2 &operator=(const derive2 &d2)
{
base2::operator=(d2);
memd=d2.memd;
return *this;
}
int memd;
};
int main(int argc, char const *argv[])
{
derive2 d2;
derive2 b2t;
b2t=d2;
return 0;
}
如果不顯示呼叫基類的operator=,那麼子類物件的基類部分將不會被賦值
四、類繼承與解構函式
根據上面的輸出結果可以知道,物件銷燬的順序和物件建立的順序是相反的,一個子類物件銷燬時,會先執行子類的解構函式,然後是基類的解構函式,以此類推,直至最上面的基類
雖然子類物件被釋放時,會分別呼叫子類和基類的解構函式,但是,子類的解構函式只負責釋放子類的成員所佔有的資源,子類中對應的基類部分由基類的解構函式進行釋放
參考
《C++ Primer》
歡迎大家評論交流,作者水平有限,如有錯誤,歡迎指出
相關文章
- C++派生類的拷貝構造C++
- 區分:派生類指定基類建構函式、繼承構造、委託構造函式繼承
- C++語言之結構體、類、建構函式、拷貝建構函式C++結構體函式
- C++ 類建構函式和解構函式C++函式
- C++之Big Three:拷貝構造、拷貝賦值、解構函式探究C++賦值函式
- C++拷貝建構函式(深拷貝,淺拷貝)C++函式
- c# abstract抽象類與繼承類子類的建構函式_baseC#抽象繼承函式
- 在 C++ 中子類繼承和呼叫父類的建構函式方法C++繼承函式
- 在C++中子類繼承和呼叫父類的建構函式方法C++繼承函式
- 類的建構函式和解構函式函式
- 子類繼承父類的建構函式(方法)嗎?繼承函式
- C++拷貝建構函式詳解C++函式
- C++ 拷貝建構函式詳解C++函式
- es5建構函式,es6類和類的繼承函式繼承
- 【C++】 46_繼承中的構造與析構C++繼承
- 拷貝建構函式函式
- Java零散知識點整理(二)(構造方法、繼承)Java構造方法繼承
- C++複製控制:拷貝建構函式C++函式
- 拷貝建構函式的作用函式
- C++ 派生類函式過載與虛擬函式繼承詳解C++函式繼承
- C++的一點基本自我修養(二)--拷貝建構函式C++函式
- 類的陣列初始化後會呼叫拷貝建構函式陣列函式
- C++中建構函式,拷貝建構函式和賦值函式的詳解C++函式賦值
- C++ 建構函式和解構函式C++函式
- c/c++ 拷貝控制 建構函式的問題C++函式
- C++中的虛繼承的構造C++繼承
- C++/CLI思辨錄之拷貝建構函式C++函式
- java容器類的繼承結構Java繼承
- 繼承中構造方法的特點繼承構造方法
- 拷貝建構函式中的陷阱函式
- 構造和解構函式呼叫順序函式
- C++ | 類繼承C++繼承
- java關於繼承父類,需要實現父類中的構造方法Java繼承構造方法
- PHP 手冊 (類與物件) 學習筆記五:建構函式和解構函式PHP物件筆記函式
- C++:String物件的構造及深拷貝C++物件
- C++,繼承,基類和派生類指標間賦值等知識C++繼承指標賦值
- js建構函式的繼承JS函式繼承
- 繼承中的建構函式繼承函式