C++派生类的构造函数和析构函数

        派生类不仅继承了基类的成员,还添加了新的成员进行了功能的扩充。因此在建立派生类的实例对象时,不仅要初始化派生类对象的基类成员,还要对派生类的新增成员进行初始化。但是由于基类的构造函数和析构函数不能继承,因此派生类构造函数必须负责调用基类构造函数,并对其所需要的参数进行设置。同时,对派生类对象的清理工作也需要加入新的析构函数。
        13.1        派生类的构造函数
        派生类的数据成员由所有基类的数据成员与派生类新增的数据成员共同组成。构造派生类的对象时,必须对全部数据成员进行初始化。因此,派生类的构造函数必须要以合适的初值作为参数,调用基类的构造函数用以初始化基类的数据成员,并对新增的数据成员进行初始化。
        派生类构造函数格式如下:
                <派生类名>::<派生类名>(<总参数>):<基类名>(<参数表>),......<成员名>(<参数表>)
                {
                       <派生类构造函数体> 
                }
        派生类的构造函数名与类名相同。在构造函数的参数表中,给出了初始化基类数据以及新增数据成员所需的全部参数。在参数表之后的成员初始化列表中,列出需要使用参数进行初始化地基类名和成员名以及各自的参数表,各项之间使用逗号分隔。
        派生类有多个基类时,处于同一层次的各个基类的构造函数的调用顺序取决于定义派生类时声明的顺序(自左向右),而与在派生类构造函数的初始化列表中给出的顺序无关。如果派生类的基类也是一个派生类,则每个派生类只需负责它的直接基类构造,依次上溯。
        建立派生类对象时,构造函数的执行顺序如下:
        (1)调用基类的构造函数对基类数据成员进行初始化,调用顺序按照各个基类被继承时声明的顺序(自左向右)。
        (2)对新增成员函数进行初始化,执行顺序按照各个成员在类中声明的顺序(自上而下)。
        (3)执行派生类的构造函数体。
        派生类的构造函数只有在需要的时候才必须定义。派生类构造函数提供了将参数传递给基类构造函数的途径,以保证在基类进行初始化时能够获得必要的数据。因此如果基类的构造函数定义了一个或多个参数时,派生类必须定义构造函数。
        如果基类中定义了默认构造函数或根本没有定义任何一个构造函数(此时由编译器自动产生默认构造函数)时,在派生类构造函数定义中可以省略对基类的调用,即省略“<基类名>(<参数表>)”。
        如果新增成员中包括成员对象,成员对象的处理情况与基类相同。
        当所有基类和成员对象的构造函数可以省略,并且也可以不在初始化列表中对其他数据成员进行显式初始化时。可以省略派生类构造函数的初始化列表。
        例1        分析下列程序的输出结果

#include<iostream>
using namespace std;
class Base1
{
private:
	int b1;
public:
	Base1(int i) :b1(i) { cout << "Base1构造函数" << endl; }
	void Point() const { cout << b1 << endl; }
};
class Base2
{
private:
	int b2;
public:
	Base2(int i) :b2(i) { cout << "Base2构造函数" << endl; }
	void Point() const { cout << b2 << endl; }
};
class Base3
{
private:
	int b3;
public:
	Base3() :b3(0) { cout << "Base3构造函数" << endl; }
	void Point() const { cout << b3 << endl; }
};
class Member
{
private:
	int m;
public:
	Member(int i) :m(i) { cout << "Menber构造函数" << endl; }
	int Getm() const { return m; }
};
class Derived:public Base1,public Base2,public Base3
{
private:
	int d;
	Member mem;
public:
	Derived(int i, int j, int k, int l);
	void Point();
};
Derived::Derived(int i, int j, int k, int l):Base1(i),Base2(j),mem(k),d(l)
{
	cout << "Derived构造函数" << endl;
}
void Derived::Point()
{
	Base1::Point();
	Base2::Point();
	Base3::Point();
	cout << mem.Getm() << endl;
	cout << d << endl;
}
int main()
{
	Derived obj1(1, 2, 3, 4);
	obj1.Point();
	return 0;
}

        构造函数的参数表中给出了基类及新增成员所需的全部参数,初始化列表中分别给定了各个基类及成员名和各自参数,各项之间由逗号分隔。这里要注意两个问题:
        (1)在初始化列表中并没有显式的给出对全部基类构造函数的调用。如果一个基类同时声明了默认构造函数和带有参数的构造函数,那么在派生类构造函数的声明中,既可以显式给出基类名和相应参数,也可以完全不给出基类名,系统会自动调用相应构造函数。
        (2)初始化列表中基类名和成员名的排序是任意的,但对它们的调用必须遵循以下顺序,即先调用基类的构造函数,再对新定义成员进行初始化(其中包括了对成员对象构造函数的调用),最后执行派生类构造函数体。其中多个基类构造函数的调用顺序按照它们被继承时声明的顺序自左向右进行,多个成员的初始化顺序按照它们在类中声明的顺序自上而下进行。
        13.2        派生类的析构函数
        与构造函数相同,派生类的析构函数在执行过程中也要对基类和新增成员进行操作,但它们的执行过程与构造函数严格相反,即:
        (1)对派生类新增成员进行清理,如果新增成员中包括成员对象,要调用成员对象的析构函数对成员对象进行清理。
        (2)调用基类析构函数,对基类成员进行清理。
        派生类析构函数的定义与基类无关,与没有继承关系的类中的析构函数的定义完全相同。它只负责对新增成员进行清理工作,系统它会自己调用基类及成员对象析构函数进行相应的清理工作。
        例2        分析下列程序的输出结果

#include<iostream>
using namespace std;
class Base
{
private:
	int b1,b2;
public:
	Base() :b1(0), b2(0) { cout << "Base无参构造" << endl; }
	Base(int i,int j) :b1(i),b2(j) { cout << "Base构造函数" << b1 << "," << b2 << endl; }
	~Base() { cout << "Base析构函数" << b1 << "," << b2 << endl; }
	void Point() const { cout << b1<<","<<b2<<","; }
};
class Derived:public Base
{
private:
	int d;
public:
	Derived() :d(0) {}
	Derived(int i, int j, int k);
	~Derived();
	void Point();
};
Derived::Derived(int i, int j, int k):Base(i,j),d(k)
{
	cout << "Derived构造函数"<<d << endl;
}
Derived::~Derived()
{
	cout << "Derived析构函数" <<d<< endl;
}
void Derived::Point()
{
	Base::Point();
	cout << d << endl;
}
int main()
{
	Derived d1(1, 2, 3);
	Derived d2(-1, -2, -3);
	d1.Point();
	d2.Point();
	return 0;
}

参考《全国计算机等级考试二级教程——C++语言程序设计》

  • 13
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值