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++之Big Three:拷貝構造、拷貝賦值、解構函式探究C++賦值函式
- 類的建構函式和解構函式函式
- C++拷貝建構函式(深拷貝,淺拷貝)C++函式
- C++拷貝建構函式詳解C++函式
- es5建構函式,es6類和類的繼承函式繼承
- 【C++】 46_繼承中的構造與析構C++繼承
- C++ 派生類函式過載與虛擬函式繼承詳解C++函式繼承
- C++ 建構函式和解構函式C++函式
- Java零散知識點整理(二)(構造方法、繼承)Java構造方法繼承
- C++中建構函式,拷貝建構函式和賦值函式的詳解C++函式賦值
- 類的陣列初始化後會呼叫拷貝建構函式陣列函式
- c/c++ 拷貝控制 建構函式的問題C++函式
- C++:String物件的構造及深拷貝C++物件
- PHP 手冊 (類與物件) 學習筆記五:建構函式和解構函式PHP物件筆記函式
- C++ | 類繼承C++繼承
- 構造和解構函式呼叫順序函式
- Kotlin之類繼承結構Kotlin繼承
- js建構函式的繼承JS函式繼承
- 繼承中的建構函式繼承函式
- java關於繼承父類,需要實現父類中的構造方法Java繼承構造方法
- C++,繼承,基類和派生類指標間賦值等知識C++繼承指標賦值
- 建構函式的prototype與各種繼承函式繼承
- 繼承中構造方法的特點繼承構造方法
- Javascript繼承2:建立即繼承—-建構函式繼承JavaScript繼承函式
- C++入門記-建構函式和解構函式C++函式
- 類的繼承_子類繼承父類繼承
- JS 建構函式與類JS函式
- PHP 抽象類繼承抽象類時的注意點PHP 抽象類繼承抽象類時的注意點PHP抽象繼承
- Javascript知識點:淺拷貝和深拷貝JavaScript
- [JavaScript]原型、原型鏈、建構函式與繼承JavaScript原型函式繼承
- C++:建構函式的分類和呼叫C++函式
- 繼承 基類與派生類繼承
- Java建構函式的繼承問題Java函式繼承
- 建構函式、原型、原型鏈、繼承函式原型繼承
- C++虛繼承原理與類佈局分析C++繼承
- 建構函式,拷貝賦值函式的N種呼叫情況函式賦值