派生类的构造和析构
(1)基类的构造函数不被继承
(2)派生类需要定义自己的构造函数
(1)可用using语句继承基类构造函数
(2)但是只能初始化从基类继承的成员
派生类新增成员可以通过类内初始值进行初始化
(3)语法形式:
using B::B
建议:如果派生类有自己新增的成员,且需要通过构造函数初始化,则派生类要自定义构造函数
(1)派生类新增成员:派生类定义构造函数初始化
(2)继承来的成员:自动调用基类构造函数进行初始化
(3)派生类的构造函数需要给基类的构造函数传递参数
派生类只有一个直接基类的情况,是单继承,单继承时,派生类的构造函数只需要给一个直接基类构造函数传递参数。
单继承时构造函数的定义和语法
派生类名::派生类名(基类所需的形参,本类成员所需的形参):基类名(参数表),本类成员初始化列表
{
//其他初始化
}
Ex:
#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 constructor 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(基类1初始化参数表),
基类名2(基类2初始化参数表),
...
基类名n(基类n初始化参数表),
本类成员初始化列表{ //其他初始化;};
(1)当基类有默认构造函数时
派生类构造函数可以不向基类构造函数传递参数
构造派生类的对象时,基类的默认构造函数将被调用
(2)如需执行基类中带参数的构造函数
派生类构造函数应为基类构造函数提供参数
派生类名::派生类名(形参表):
基类名1(参数),基类名2(参数),...,基类名n(参数),
本类成员(含对象成员)初始化列表
{
//其他初始化
};
(1)调用基类构造函数
顺序按照它们被继承时声明的顺序(从左到右)
(2)对初始化列表中的成员进行初始化
顺序按照它们在类中定义的顺序(不是初始化列表的顺序)
对象成员初始化时自动调用其所属类的构造函数。由初始化列表提供参数。
(3)执行派生类的构造函数体中的内容
Derived类继承的顺序(从左到右)先是基类2的构造函数,再是基类1的构造函数,再是基类3的构造函数
接着:按照在类中定义的顺序,先是基类1的构造函数,再是基类2的构造函数,最后是基类3的构造函数
#include <iostream> using namespace std; class Base1 {//基类Base1,构造函数有参数 public: Base1(int i) { cout << "Constructing Base1 " << i << endl; } }; class Base2 {//基类Base2,构造函数有参数 public: Base2(int j) { cout << "Constructing Base2 " << j << endl; } }; class Base3 {//基类Base3,构造函数无参数 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; }
(1)编译器会在需要时生成一个隐含的复制构造函数
(2)先调用基类的复制构造函数
(3)再为派生类新增的成员执行复制
(1)一般都要为基类的复制构造函数传递参数
(2)复制构造函数只能接受一个参数,既用来初始化派生类定义的成员,也将被传递给基类的复制构造函数
(3)基类的复制构造函数形参类型是基类对象的引用,实参可以是派生类对象的引用
(4)例如 C::C(const C &c1):B(c1){...}
(1)析构函数不被继承,派生类如果需要,要自行声明析构函数
(2)声明方法与无继承关系时类的析构函数相同
(3)不需要显示地调用基类的析构函数,系统会自动隐式调用
(4)先执行派生类析构函数的函数体,再调用基类的析构函数
析构函数执行的顺序与构造函数相反,比如二中的例子,析构函数执行顺序与构造函数执行顺序相反