继承是C++的重要属性:
在C++中有:
公有继承(public)、私有继承(private)、保护继承(protected)是常用的三种继承方式。
1. 公有继承(public)
公有继承的特点是基类的公有成员和保护成员作为派生类的成员时,它们都保持原有的状态,而基类的私有成员仍然是私有的,不能被这个派生类的子类所访问。
2. 私有继承(private)
私有继承的特点是基类的公有成员和保护成员都作为派生类的私有成员,并且不能被这个派生类的子类所访问。
3. 保护继承(protected)
保护继承的特点是基类的所有公有成员和保护成员都成为派生类的保护成员,并且只能被它的派生类成员函数或友元访问,基类的私有成员仍然是私有的。
下面列出三种不同的继承方式的基类特性和派生类特性。
| public | protected | private |
公有继承 | public | protected | 不可见 |
私有继承 | private | private | 不可见 |
保护继承 | protected | protected | 不可见 |
在上图中:
1)基类成员对派生类都是:共有和保护的成员是可见的,私有的的成员是不可见的。
2)基类成员对派生类的对象来说:要看基类的成员在派生类中变成了什么类型的成员。如:私有继承时,基类的共有成员和私有成员都变成了派生类中的私有成员,因此对于派生类中的对象来说基类的共有成员和私有成员就是不可见的。
为了进一步理解三种不同的继承方式在其成员的可见性方面的区别,下面从三种不同角度进行讨论。
(1) 基类成员对其对象的可见性:
公有成员可见,其他不可见。这里保护成员同于私有成员。
(2) 基类成员对派生类的可见性:
公有成员和保护成员可见,而私有成员不可见。这里保护成员同于公有成员。
(3) 基类成员对派生类对象的可见性:
公有成员可见,其他成员不可见。
所以,在公有继承时,派生类的对象可以访问基类中的公有成员;派生类的成员函数可以访问基类中的公有成员和保护成员。这里,一定要区分清楚派生类的对象和派生类中的成员函数对基类的访问是不同的。
(1) 基类成员对其对象的可见性:
公有成员可见,其他成员不可见。
(2) 基类成员对派生类的可见性:
公有成员和保护成员是可见的,而私有成员是不可见的。
(3) 基类成员对派生类对象的可见性:
所有成员都是不可见的。
所以,在私有继承时,基类的成员只能由直接派生类访问,而无法再往下继承。
这种继承方式与私有继承方式的情况相同。两者的区别仅在于对派生类的成员而言,对基类成员有不同的可见性。
上述所说的可见性也就是可访问性。
关于可访问性还有另的一种说法。这种规则中,称派生类的对象对基类访问为水平访问,称派生类的派生类对基类的访问为垂直访问。
一个私有的或保护的派生类不是子类,因为非公共的派生类不能做基类能做的所有的事,就是指在公开场合,但是在类内部可以的
一、引言
在C++中,类是提供封装的逻辑单位,类的每一个对象都包含有描述其自身状态的数据集合,并且通过接收特定的消息来处理这个数据集合。如果程序设计人员能够通过增加、修改或替换指定类的部分内容的方法对该类进行剪裁,就可以适应不同的应用,从而在很大程度上增强了数据封装的价值,而接下来要讨论的继承就完全可以实现这种操作。
二、与继承有关的基本概念
继承是一个进程,通过继承,一个对象可以获得另一个对象的属性(包括函数),并可向其中加入属于自己的一些特征。作为C++语言的一种重要机制,用继承的方法可以自动为一个类提供来自另一个类的操作和数据结构,进而使程序设计人员在一个一般的类的基础上很快建立一个新的类,而不必从零开始设计每个类。
当一个类被其他的类继承时,被继承的类称为基类(可不是鸡肋^_^),又称为父类。
继承其他类属性的类称为派生类,又称为子类。
一般情况下,继承的进程起源于一个基类的定义,基类定义了其所有派生类的公有属性。从本质上讲,基类具有同一类集合中的公共属性,派生类继承了这些属性,并且增加了自己特有的属性。从任何已存在的类继承的实质就是建造新的派生类。
三、单重继承、多重继承与继承链
从一个基类派生的继承称为单继承,换句话说,派生类只有一个直接基类。单继承声明语句的常用格式为:
class 派生类名: 访问控制关键字 基类名 |
与此相对地,从多个基类派生的继承称为多继承或多重继承,也就是说,一个派生类有多个直接基类。在某些面向对象的语言(如Java)中不支持类间的多重继承而只支持单重继承,即一个类至多只能有一个直接父类,因此实现类似的功能需要借助接口等其他机制。而在C++中提供了多重继承的语法支持,使得问题变得简单了许多。多重继承声明语句的常用格式为:
class 派生类名: 访问控制关键字 基类名1, 访问控制关键字 基类名2,... |
除了多重继承之外,一个派生类继承多个基类还有一种方法,就是把派生类作为基类再次供别的类继承,产生多层次的继承关系。例如类A派生类B,类B派生类C,则称类A是类B的直接基类,类B是类C的直接基类,类A是类C的间接基类。类的层次结构也叫做继承链。还是上面的例子,当建立类C的对象时,类A 的构造函数最先被调用,接下来被调用的是类B的构造函数,最后是类C的构造函数。析构函数的调用顺序正好相反。当一个派生类继承有层次的类时,继承链上的每个派生类必须将它需要的变量传递给它的基类。
四、公有派生和私有派生
在继承声明语句中,访问控制关键字用于说明在基类定义中所声明的成员和成员函数能够在多大范围内被派生类所访问。访问控制关键字可为public, private或protected。如果访问控制关键字为public,则称派生类从基类公有继承,也称公有派生。如果访问控制关键字为 private,则称派生类从基类私有继承,也称私有派生。现在笔者将公有继承和私有继承的具体区别列表如下。
通过上表,我们可以将两种派生的特点总结如下:
基类成员 | 基类private成员 | 基类public成员 | ||
派生方式 | private | public | private | public |
派生类成员 | 不可见 | 不可见 | 可见 | 可见 |
外部函数 | 不可见 | 不可见 | 不可见 | 可见 |
(1)无论哪种派生方式,基类中的private成员在派生类中都是不可见的。也就是说,基类中的private成员不允许外部函数或派生类中的任何成员访问。
(2)public派生与private派生的不同点在于基类中的public成员在派生类中的访问属性:
public派生时,基类中的public成员相当于派生类中的public成员。
private派生时,基类中的public成员相当于派生类中的private成员。
因此,private派生确保基类中的方法只能被派生类的对象的方法间接使用,而不能被外部使用。public派生使派生类对象与外部都可以直接使用基类中的方法,除非这些方法已经被重新定义。
五、保护成员与保护派生
如果想做到基类成员只由有派生血缘关系的成员访问,而不被无血缘关系的对象成员访问,无论用公有派生还是私有派生都无法做到。因为基类成员中的私有成员是别的类(包括派生类)成员不能访问的,而基类中的公有成员在public派生时,不仅可以由派生类对象成员访问,也可以由外部函数访问;而在 private派生时,基类中的公有成员虽然允许派生类对象中的成员访问,不允许外部访问,可是再派生出下一级时,由于基类的所有成员已经被私有化,其它类成员也不可再访问。实现只许有派生血缘关系的对象成员访问的方法,是在基类中使用具有另一种访问属性的成员——protected成员。
protected成员是一种血缘关系内外有别的成员。它对派生对象而言,是公有成员,可以访问;对血缘关系外部而言,与私有成员一样被隐藏。
此外,除了允许使用private与public两种派生方式之外,C++还允许使用protected派生方式。现在将三种访问属性不同的成员经三种派生后在派生类中访问属性的变化情况总结如下表,是对上一表格的增进和补充。
派生方式 | 基类的public成员 | 基类的protected成员 | 基类的private成员 | 派生方式引起的访问属性变化概括 |
private派生 | 变为private成员 | 变为private成员 | 不可见 | 基类中的非私有成员都成为派生类中的私有成员 |
protected派生 | 变为protected成员 | 仍为protected成员 | 不可见 | 基类中的非私有成员都成为派生类中的保护成员 |
public派生 | 仍为public成员 | 仍为protected成员 | 不可见 | 基类中的非私有成员在派生类中的访问属性保持不变 |
需要注意的是,基类的private成员无论经过何种派生,在派生类中都是不可见的。
六、友元类和友元函数
在类的学习中,我们都了解了友元,友元可以访问指定类的私有和受保护的自定义成员,如果不是指定的成员,则不能被访问
友元类
(1) 友元函数不是类成员函数,所以不能被继承;
(2) 友元关系是单向的,不具有交换性;
若B类是A类的友元,不一定A类就是B类的友元
(3) 友元关系不能被传递,若B类是A类的友元,C类是B类的友元,C类不一定是A类的友元
友元注意事项
a、友元函数可访问类的私有成员,但不是类的成员函数;
b、友元函数不能用const修饰;
c、友元函数可以在类定义的任何地方声明,不受类访问限定
符限制;
d、一个函数可以是多个类的友元函数;
e、友元函数的调用与普通函数的调用和原理相同;
f、友元关系不能继承,基类的友元对派生类的成员没有特殊的访问权限。如果基类被授予友元关系,则只有基类具有特殊的访问权限。该基类的派生类不能访问授予友元关系的类。
例子:http://blog.csdn.net/zhaori/article/details/1700356