继承与派生
一、继承与派生的概念
1.继承与类
继承是指一个事物可以继承其父辈全部或部分特性,同时本身还可以有自己的特性。
2.类继承
子类继承父类,也可以称为父类派生了子类。被继承的类也被称为基类、超类或父类,在基类基础上建立的新类称为派生类或者子类。
3.类层次关系的描述方法
类层次
多层派生 多层继承
一个基类可以有多个派生类。
二、定义基类与派生类
定义基类
基类定义基本的数据成员与成员函数。
1.基类成员函数
2.访问控制和继承
在基类中,public和private关键字具有普通含义:用户代码可以访问类的public成员而不能访问private成员,private成员只能由基类的成员和友元访问。派生类对基类的public和private成员的访问权限与程序任意其他部分一样(即可以访问public而不能访问private)。
有时作为基类的一些成员,可以使用protected关键字,protected成员可以被派生类对象访问而不能被普通用户访问。
定义派生类
一般形式:
class 派生类名:[继承方式]基类名列表
{
派生类新增成员
};
继承方式包括:public、private、protected,若此项为空,则默认private,基类名列表是已定义的基类名的列表,列表项以逗号分割。派生类可指定多个基类。继承单个基类为单继承,继承多个基类为多继承。
1.派生类构成
2.派生类对象包含基类对象作为子对象
3.派生类中的函数可以使用基类的成员
4.用作基类的类必须是已定义的
三、基类成员在派生类中的可访问性
公用继承
在定义一个派生类时将基类的继承方式指定为public,称为公用继承。
用公用继承的派生类称为公用派生类,其基类称为公用基类。
采用公用继承方式时,基类的公用成员和保护成员在派生类中仍然保持其公用成员和保护成员的属性,而基类的私有成员在派生类中并没有成为派生类的私有成员,它依然是基类的私有成员,只有基类的成员函数可以引用它,而不能被派生类的成员函数引用,因此在派生类中是不可访问的。
私有继承
在声明一个派生类时将基类的继承方式指定为private的,成为私有继承。用私有继承方式建立的派生类称为私有派生类,其基类称为私有基类。
私有基类的公用成员和保护成员在派生类中的访问属性相当于派生类中的私有成员。
私有基类的私有成员在派生类中仍然是不可访问成员,只有基类的成员可以使用它们。
保护成员和保护继承
由protected声明的成员称为受保护成员或保护成员。从类的用户角度来看,保护成员等价于私有成员。但保护成员可以被派生类的成员函数引用。
在定义一个派生类时将基类的继承方式指定为protected,称为保护继承。
用公用继承的派生类称为保护派生类,其基类称为保护基类。
保护基类的公用成员和保护成员在派生类中都成了保护成员,其私有成员仍为基类私有,不能被派生类访问。
class Base{
private: int m;
protected: int n;
public: int t;
};
class D1: public Base{
//D1继承得到n、t,不能访问m。
}
class D2 :private Base{
//D2继承得到n、t,不能访问m。
};
class D3 :protected Base{
//D3继承得到n、t,不能访问m。
};
四、派生类的构造函数和析构函数
在设计派生类的构造函数时,不仅要考虑派生类所增加的数据成员的初始化,还应当考虑基类的数据成员初始化。要在执行派生类的构造函数时,使派生类和基类的数据成员同时得到初始化。
class Point3D: public Point2D{
public:
Point3D(double x=0.0,double y=0.0,double z=0.0):Point2D(x,y),_z(z){}
protected :
double _z;
};
如果派生类中还包含其他类的对象成员,则构造函数的调用顺序是:先调用基类构造函数,再调用成员的构造函数,最后调用派生类的构造函数执行。
在撤销一个派生类对象时,基类的子对象也被撤销。析构函数的调用次序和构造函数的调用次序相反:先调用派生类的析构函数,再调用基类的析构函数。
五、多重继承与虚基类
多重继承
多重继承是指派生类有两个或两个以上的直接基类。多重继承可以看做是单继承的扩展,派生类与每个基类之间的关系可以看做是一个单继承。
class 派生类名:<继承方式>基类名1 <,<继承方式>基类名2>
{
};
class C:public A{};
class E:public C,protected D
{
B member;
};
构造函数调用顺序:A-C-D-B-E
析构函数与构造函数调用顺序相反。
在多重继承中继承的成员同名而产生的二义性问题,可以分为下列三种情况:
1.两个基类有同名成员:
可以用基类名限定:teacher::name
2.两个基类和派生类三者都有同名成员:
派生类新增加的同名成员覆盖了基类的同名成员。
注意:覆盖是指不同的成员函数,在函数名和参数个数相同、类型相匹配的情况下才发生同名覆盖。
3.多级派生中,多个基类作为派生类存在共同基类
C++提供虚基类的方法,使得在继承间接共同基类时只保留一份成员。
虚基类
在虚继承下,无论基类在派生层次中出现多少次,在派生类对象中只有一个共享的基类子对象。这样的基类被称为虚基类。
class A {};
class B {};
class C : public B,public virtual A{};
class D : public virtual A{};
class E :public C,public virtual D{};
构造函数调用顺序:A-D-B-C-E