Part7 继承与派生 7.4派生类的构造和析构
1派生类的构造函数
默认情况下:基类的构造函数不被继承,派生类需要定义自己的构造函数。
C++11 规定:可用using语句继承基类构造函数。但是只能初始化从基类继承的成员。这时派生类新增成员可以通过类内初始值进行初始化。
建议:如果派生类有自己新增的成员,且需要通过构造函数初始化,则派生类要自定义构造函数。
若不继承基类的构造函数:
继承来的成员:自动调用基类构造函数进行初始化
派生类的构造函数需要给基类的构造函数传递参数。
单继承(派生类只有一个直接基类的情况)时构造函数的定义语法:
派生类名::派生类名(基类所需的形参,本类成员所需的形参):
基类名(参数表), 本类成员初始化列表
{
//其他初始化;
};
//单继承时的构造函数举例 #include<iostream> using namespace std; class B{ public: B(); B(int i); ~B(); void print() const; private: int b; }; B::B(){ b = 0; cout << "B's default constructor called." << endl; } B::B(int i){ b = i; cout << "B's constructor called." << endl; } B::~B(){ cout << "B's destructor called." << endl; } void B::print() const{ cout << b << endl; } class C: public B{ public: C(); C(int i, int j); ~C(); void print() const; private: int c; }; C::C(){ c = 0; cout << "C's default contructor called." << endl; } C::C(int i, int j):B(i),c(j){ cout << "C's constructor called." << endl; } C::~C(){ cout << "C's destructor called." << endl; } void C::print() const{ B::print(); cout << c << endl; } int main(){ C obj(5,6); obj.print(); return 0; }
构造函数的执行顺序:
1 调用基类构造函数。
顺序按照它们被继承时声明的顺序(从左向右)。
2 对初始化列表中的成员进行初始化。
顺序按照它们在类中定义的顺序。
对象成员初始化时自动调用其所属类的构造函数。由初始化列表提供参数。
3 执行派生类的构造函数体中的内容。
2派生类构造函数举例
//7-4派生类构造函数举例 #include<iostream> using namespace std; class Base1{//基类1,构造函数有参数 public: Base1(int i){ cout << "Constructing Base1 " << i << endl; } }; class Base2{//基类2,构造函数有参数 public: Base2(int j){ cout << "Constructing Base2 " << j << endl; } }; class Base3{//基类3,构造函数无参数 public: Base3(){ cout << "Constructing Base3 *" << endl; } }; class Derived: public Base2, public Base1, public Base3{ public: Derived(int a, int b, int c, int d):Base1(a), member2(d), member1(c), Base2(b){}//此处的次序与构造函数的执行次序无关 private://派生类的私有对象成员 Base1 member1; Base2 member2; Base3 member3; }; int main(){ Derived obj(1,2,3,4); return 0; }
3派生类复制构造函数
派生类未定义复制构造函数的情况:
编译器会在需要时生成一个隐含的复制构造函数;
这个隐含复制构造函数,先调用基类的复制构造函数;
再为派生类新增的成员执行复制。
派生类定义了复制构造函数的情况:
一般都要为基类的复制构造函数传递参数。
复制构造函数只能接受一个参数,既用来初始化派生类定义的成员,也将被传递给基类的复制构造函数。
基类的复制构造函数形参类型是基类对象的引用,实参可以是派生类对象的引用
如: C::C(const C &c1): B(c1) {…}
4派生类的析构函数
析构函数不被继承,派生类如果需要,要自行声明析构函数。
声明方法与无继承关系时类的析构函数相同。
不需要显式地调用基类的析构函数,系统会自动隐式调用。
先执行派生类析构函数的函数体,再调用基类的析构函数。
//7-5派生类对象析构举例 #include<iostream> using namespace std; class Base1{ public: Base1(int i){ cout << "Constructing Base1 " << i << endl; } ~Base1(){ cout << "Destructing Base1" << endl; } }; class Base2{ public: Base2(int j){ cout << "Constructing Base2 " << j << endl; } ~Base2(){ cout << "Destructing Base2" << endl; } }; class Base3{ public: Base3(){ cout << "Constructing Base3 *" << endl; } ~Base3(){ cout << "Destructing Base3" << endl; } }; class Derived: public Base2, public Base1, public Base3{ public: Derived(int a, int b, int c, int d):Base1(a), member2(d), member1(c), Base2(b){} private: Base1 member1; Base2 member2; Base3 member3; }; int main(){ Derived obj(1,2,3,4); return 0; }