详解派生类构造函数与析构函数
派生类构造函数与析构函数
1.派生类构造函数:
派生类不能继承基类的构造函数,必须自己定义构造函数进行新增数据成员初始化工作,如果想同时初始化基类数据成员,必须调用基类构造函数。
(1)简单派生类构造函数:
1 #include <iostream> 2 3 #include <string> 4 5 using namespace std; 6 7 8 9 class St1 10 11 { 12 13 public: 14 15 //基类构造函数,初始化成员变量 16 17 St1(int n, string na, char se):num(n),name(na),sex(se){cout<<"St1"<<endl;} 18 19 ~St1(){cout<<"~St1"<<endl;} 20 21 protected: 22 23 int num; 24 25 string name; 26 27 char sex; 28 29 }; 30 31 32 33 class St2:public St1 34 35 { 36 37 public: 38 39 //派生类调用基类构造函数 40 41 St2(int n, string na, char se, int a, string add):St1(n,na,se),age(a),addr(add){cout<<"St2"<<endl;} 42 43 ~St2(){cout<<"~St2"<<endl;} 44 45 void display(){cout<<num<<'\t'<<name<<'\t'<<sex<<'\t'<<age<<'\t'<<addr<<endl; } 46 47 private: 48 49 int age; 50 51 string addr; 52 53 }; 54 55 int main() 56 57 { 58 59 St2 s(200, "ace", 'M', 25, "Hangzhou"); 60 61 s.display(); 62 63 return 0; 64 65 }
输出:
(2)包含子对象的派生类构造函数:
#include <iostream> #include <string> using namespace std; class St1 { public: //基类构造函数,初始化成员变量 St1(int n, string na, char se):num(n),name(na),sex(se){cout<<"St1"<<endl;} ~St1(){cout<<"~St1"<<endl;} void display1(){cout<<num<<'\t'<<name<<'\t'<<sex<<'\t'; } protected: int num; string name; char sex; }; class St2:public St1 { public: //派生类调用基类构造函数 St2(int n, string na, char se, int n_m, string na_m, char se_m, int a, string add):St1(n,na,se),monitor(n_m,na_m,se_m) {age = a; addr = add;cout<<"St2"<<endl;} ~St2(){cout<<"~St2"<<endl;} void display2(){display1();cout<<age<<'\t'<<addr<<endl; } void showmonitor() {cout<<"Monitor is:"<<endl; monitor.display1(); cout<<endl;} private: int age; string addr; St1 monitor;//包含子对象 }; int main() { St2 s(200, "ace", 'M', 11, "HH", 'M', 26, "Shanghai"); s.display2(); s.showmonitor(); return 0; }
输出:
几点注意:
1).在调用派生类构造函数之前,系统会先调用基类的构造函数;如果派生类构造函数列表中包含对基类子对象成员的初始化(如上例中的monitor),每个基类子对象初始化时也要调用一次基类构造函数;最后才是派生类调用自身的构造函数来初始化自身新增的成员(如上例中的age,addr)。执行顺序就是派生类构造函数列表顺序:
St2(int n, string na, char se, int n_m, string na_m, char se_m, int a, string add):St1(n,na,se)[1],monitor(n_m,na_m,se_m)[2]
{age = a; addr = add;cout<<"St2"<<endl;}[3]
2).当然,对上述三种类型进行参数初始化时,会出现以下几种特殊情况:
(a) 派生类新增成员不需要进行初始化(很常见):
St2(int n, string na, char se, int n_m, string na_m, char se_m):St1(n,na,se)[1],monitor(n_m,na_m,se_m)[2]{}
(b)基类没有定义构造函数或者基类构造函数无参—调用基类默认构造函数
St2(int a, string add ){age = a; addr = add;cout<<"St2"<<endl;}[3]
(c) 基类中重载了构造函数,既有有参的又有无参的,具体调用哪个视派生类构造函数参数个数而定。
2.派生类的析构函数【留坑---虚析构函数】:
(1).正如派生类不能继承基类的构造函数,派生类也不能继承基类的析构函数,派生类的清理工作由派生自身析构函数负责,基类的清理工作由基类析构函数负责。
(2).析构函数的调用顺序正好和构造函数调用顺序相反,即先调用派生类析构函数清理新增的成员,再调用子对象析构函数(基类析构函数)清理子对象,最后再调用基类析构函数清理基类成员。