派生类从基类继承的过程
派生类从基类继承的过程可以分为三个步骤:吸收基类成员、修改基类成员和添加新成员。
吸收基类成员就是代码复用的过程,修改基类成员和添加新成员实现的是对原有代码的扩展,而代码的复用和扩展是继承与派生的主要目的。
基于上一讲中雇员的例子,写一个雇员类和其派生类-销售人员类。这里只给出部分声明,大家先了解下派生过程。
class employee // 雇员类
{
public:
employee(); // 构造函数
~employee(); // 析构函数
void promote(int); // 升级函数
void getSalary(); // 计算工资
protected:
char *m_szName; // 雇员姓名
int m_nGrade; // 级别
float m_fSalary; // 工资
};
class salesman : public employee
{
public:
salesman();
~salesman();
void getSalary(); // 计算工资
private:
float m_fProportion; // 提成比例
float m_fSalesSum; // 当月总销售额
};
以上面的代码为例详细讲下三个步骤。
吸收基类成员
派生类从基类继承时首先就是吸收基类成员,将基类成员中除了构造函数和析构函数外的所有其他成员全部接收。这里要注意,基类的构造函数和析构函数都不能被派生类继承。
上例中,employee类除构造函数和析构函数外的所有成员:promote(int)函数、getSalary()函数,以及数据成员m_szName、m_nGrade和m_fSalary,都被派生类salesman继承过来。
修改基类成员
派生类修改基类成员的方式有两种,
1)是通过设置派生类声明中的继承方式,来改变从基类继承的成员的访问属性;
2)是通过在派生类中声明和基类中数据或函数同名的成员,覆盖基类的相应数据或函数。一旦我们在派生类中声明了一个和基类某个成员同名的成员,那么派生类这个成员就会覆盖外层的同名成员。这叫做同名覆盖。需要注意的是,要实现函数覆盖不只要函数同名,函数形参表也要相同,如果函数形参表不同只有名字相同则属于前面所说的重载。
上例中,salesman类的getSalary函数覆盖了employee类的同名函数。比如,我们定义了一个salesman类的对象A,则A.getSalary()调用的是salesman类中的getSalary函数而不是基类employee中的。
添加新成员
代码的扩展是继承与派生的主要目的之一,而添加新成员是实现派生类在基类基础上扩展的关键。
上例中,派生类salesman就添加了两个新数据成员m_fProportion和m_fSalesSum。可见,能够添加新成员还是很方便的,我们在软件开发中可以根据实际需要为派生类添加新的数据成员或函数成员。
上面说过,派生类不能从基类继承构造函数和析构函数。但是派生类同样需要有初始化和清理,所以我们需要为派生类添加新的构造函数和析构函数,就像上例中,派生类salesman中就添加了新的构造函数salesman()和新的析构函数~salesman()。