继承是面向对象编程的一个重要特性,在使用C++语言的软件开发中,继承是必不可少的。C++中把遗传的功能称为继承,将遗传加变异的功能称为派生。
1、继承的形式
(1)单继承
定义格式如下:
class <子类名>:<继承方式> <父类名>、
{
<子类新定义成员>
};
在C++中,<继承方式>有如下三种:
public:表示公有继承
private:表示私有继承
protected:表示保护继承
(2)多继承
在众多面对对象语言中,基本上只支持单继承,即子类的父类只有一个,父类可以派生出多个子类。虽然单继承可以解决大多问题,但在一些场合使用单继承达到预期功能需求很复杂麻烦。因此C++还采用多继承方式。
其标准格式如下:
class <子类名> :<继承方式1><父类名1>,<继承方式2><父类名2>,...
{
<子类新定义成员>
}
从定义可以看出,多继承和单继承的区别只要是多继承的父类多于一个,如果省略继承方式,将默认为私有继承。
2、三种继承方式
(1)公有继承:之前的文章中有提及类的私有成员不可以被访问,同样在公有继承后的子类中也不可以访问父类私有成员。如果想访问父类的私有成员,要使用封装隐藏的原则,将私有的数据成员隐藏起来,对外公开一个公有访问该数据成员的借楼函数。代码如下:
int get_a
{
return a;
}
公有继承的特点是父类的公有成员和保护成员偶被子类继承,且这些成员的属性保持不变,在子类中也可以访问父类的公有和保护成员。父类的私有成员不被子类继承,切不能再子类中访问。
对于公有继承方式,要搞清父类成员对于子类和子类对象的访问权限,分以下两种情况总结:
->父类成员对其子类对象的可见性
父类的 公有成员对于其子类对象来说是可见的,其他成员隐藏,不可以直接访问。这里父类的保护成员被访问的权限等同于私有成员。
->父类成员对其子类的可见性
父类的公有和保护成员可见,而私有成员被隐藏,不可直接访问。这里父类的保护成员被访问的权限等同于公有成员。
(2)私有继承
私有继承中,父类的公有成员和保护成员都作为子类的私有成员,并且不能被这个子类的对象进行访问。
(3)保护继承
再保护继承中,父类所有公有成员和保护成员都成为子类的保护成员,且只和能被他的子类成员函数或者友元访问,父类的私有成员依然是私有的,子类的对象不能直接访问父类的成员。
使用保护继承方式的父类公有或保护成员可以传递给孙子类,在孙子类中也可以被正常访问。在保护继承中,父类的公有成员到子类中,其属性直接降级为保护成员。
3、继承的构造函数和析构函数
在这个问题中,一定要注意三个问题:构造函数的构造顺序、析构函数的析构顺序、子类构造函数的初始规则。
通过代码测试可以知道系统会首先调用父类的构造函数,将父类对象相关成员明确后,才可以被子类对象使用。构造的顺序是先父类再子类,析构的顺序是先子类再父类。即构造和析构的顺序相反。
4、虚继承
C++使用虚拟继承(Virtual Inheritance),解决从不同途径继承来的同名的数据成员在内存中有不同的拷贝造成数据不一致问题,将共同基类设置为虚基类。这时从不同的路径继承过来的同名数据成员在内存中就只有一个拷贝,同一个函数名也只有一个映射。
解决的问题:
解决了二义性问题,也节省了内存,避免了数据不一致的问题。
虚继承中的构造和析构顺序:
首先执行虚基类的构造函数,多个虚基类的构造函数按照被继承的顺序构造;
执行基类的构造函数,多个基类的构造函数按照被继承的顺序构造;
执行成员对象的构造函数,多个成员对象的构造函数按照申明的顺序构造;
执行派生类自己的构造函数;
析构以与构造相反的顺序执行;