不是所有的函數都能自動地從基類繼承到派生類中的。
構造函數和析構函數是用來處理對象的創建和析構的,它們只知道對在它們的特殊層次的對象做什么。
所以,在整個層次中的所有的構造函數和析構函數都必須被調用,也就是說,構造函數和析構函數不能被繼承。
子類的構造函數會顯示的調用父類的構造函數或隱式的調用父類的默認的構造函數進行父類部分的初始化。
析構函數也一樣。它們都是每個類都有的東西,如果能被繼承,那就沒有辦法初始化了。
此外,在創建子類對象時,為了初始化從父類繼承來的數據成員,系統需要調用其父類的構造方法。
如果沒有顯式的構造函數,編譯器會給一個默認的構造函數,並且該默認的構造函數僅僅在沒有顯式地聲明構造函數情況下創建。
構造原則如下:
1. 如果子類沒有定義構造方法,則調用父類的無參數的構造方法。
2. 如果子類定義了構造方法,不論是無參數還是帶參數,在創建子類的對象的時候,首先執行父類無參數的構造方法,然后執行自己的構造方法。
3. 在創建子類對象時候,如果子類的構造函數沒有顯示調用父類的構造函數,則會調用父類的默認無參構造函數。
4. 在創建子類對象時候,如果子類的構造函數沒有顯示調用父類的構造函數且父類自己提供了無參構造函數,則會調用父類自己的無參構造函數。
5. 在創建子類對象時候,如果子類的構造函數沒有顯示調用父類的構造函數且父類只定義了自己的有參構造函數,則會出錯(如果父類只有有參數的構造方法,則子類必須顯示調用此帶參構造方法)。
6. 如果子類調用父類帶參數的構造方法,需要用初始化父類成員對象的方式,比如:
#include <iostream.h> class animal { public: animal(int height, int weight) { cout<<"animal construct"<<endl; } … }; class fish:public animal { public: fish():animal(400,300) { cout<<"fish construct"<<endl; } … }; void main() { fish fh; }
在fish類的構造函數后,加一個冒號(:),然后加上父類的帶參數的構造函數。這樣,在子類的構造函數被調用時,系統就會去調用父類的帶參數的構造函數去構造對象。這種初始化方式,還常用來對類中的常量(const)成員進行初始化,如下面的代碼所示:
class point { public: point():x(0),y(0) private: const int x; const int y; };
再來看一段代碼:
#include<iostream> #include<string> using namespace std; class Student//聲明基類 { protected: int num; string name; char sex; public: Student(int n,string nam,char s)//定義基類(含參)構造函數 { num=n; name=nam; sex=s; } }; class Student1 : public Student//聲明公用派生類Student1 { private: int age; string addr; public: Student1(int n,string nam,char s,int a,string ad):Student(n,nam,s) //定義派生類構造函數 { age=a; addr=ad; } void show() { cout<<"num:"<<num<<endl; cout<<"name:"<<name<<endl; cout<<"sex:"<<sex<<endl; cout<<"age:"<<age<<endl; cout<<"address"<<addr<<endl<<endl; } ~Student1 (){} };
派生類構造函數一般形式為
派生類構造函數名(總參數表):基類構造函數名(參數表)
{派生類中新增數據成員初始化語句}
冒號“:”前面部分是派生類構造函數的主干,他和以前介紹過的構造函數的形式相同,但它的總參數表中包括基類構造函數所需的參數和對派生類新增的數據成員初始化所需的參數。冒號“:”后面部分是要調用的基類構造函數及其參數。
從上面列出的派生類Student1構造函數首行中可以看到,派生類構造函數名(Student1)后面括號內的參數表中包括參數的類型和參數名(如int n) ,
而基類構造函數名后面括號內的參數表列只有參數名而不包括參數類型(如n,num,s),因為在這里不是定義基類構造函數,而是調用基類構造函數,因此這些參數是實參而不是形參。
它們可以是常量、全局變量和派生類構造參數總參數表中的參數。
從上面列出的派生類Student1構造函數中可以看到:調用基類構造函數Student時給出3個參數(n,nam,s),這是和定義基類構造函數時指定的參數相匹配的。
派生類構造函數Student1有5個參數,其中前3個是用來傳遞給基類構造函數,后面兩個(a和ad)是用來對派生類所增加的數據成員初始化的。
2.派生類的析構函數
析構函數的作用是在對象撤銷之前,進行必要的清理工作。
在派生時,派生類是不能繼承基類的析構函數的,也需要通過派生類的析構函數去調用基類的析構函數。在派生類中可以根據需要定義自己的析構函數,用來地派生類中所增加的成員進行清理工作。基類的清理工作任然由基類的析構函數負責。
調用的順序與構造函數正好相反:先執行派生類自己的析構函數,對派生類新增加的成員進行清理,然后調用子對象的析構函數,對子對象進行清理,最后調用基類的析構函數,對基類進行清理。
參考:
https://www.cnblogs.com/shmilxu/p/4849097.html
https://blog.csdn.net/T_ambition/article/details/80490374