(本文根据《c++程序设计》(谭浩强)总结而成,整理者:华科小涛@http://www.cnblogs.com/hust-ghtao,转载请注明)
1 基本思想与概念
在传统的程序设计中,人们无法利用现有的丰富的软件资源,造成软件开发中人力、物力和时间的巨大浪费,这是因为过去的程序设计方法和计算机语言缺乏软件重用机制。而作为面向对象的语言,C++强调软件的可重用性,通过继承机制,解决了软件的可重用性问题。在编程的领域,你经常会遇到具有类似属性,但细节或行为存在细微差异的组件。在这些情况下,一种解决方案是将每个组件声明为一个类,并在每个类中实现所有的属性,这将重复实现相同的属性。另外一种解决方案就是使用继承,从同一个基类( base class)中派生出类似的类,在基类中实现通用的功能,并在派生类中覆盖基本的功能,以实现其独特的行为。
大家注意几个概念:
“继承”就是在一个已存在的类的基础上建立一个新的类,已存在的类称为“基类( base class)”或者“父类( father class)”,新建立的类称为“派生类( derived class)”或“子类( son class)”。而什么是“派生”呢?,其实“继承”和“派生”是从不同角度说的同一件事,“继承”是从子类的角度看,子类从基类那里获得基类特性的现象就是继承;“派生”是从基类的角度看,是指基类产生一个子类的过程。另外,一个派生类只从一个基类派生,这称为单继承;一个派生类有两个或多个基类称为多重继承。
2 派生类的构成
派生类中的成员包括从基类继承过来的成员和新增加的成员两大部分。从基类继承过来的成员体现了派生类从基类而获得的共性,而新增加的成员体现了派生了的个性。构造一个派生类包括3部分工作。
(1)从基类接收成员。派生类把全部的成员(不包括构造函数和析构函数)接收过来。这样就会出现一种情况:有些基类的成员在派生类中是用不到的,但是也必须继承过来,会造成数据的冗余,这就要求我们要从已有的类中选择合适的类作为基类,使派生类的结构更加合理。
(2)调整从基类接收的成员。一方面,我们可以通过指定继承方式来改变基类成员在派生类中的访问属性。另一方面,可以在派生类中声明一个与基类成员同名的成员,则派生类中的新成员会覆盖基类的同名成员,注意:如果是成员函数,不仅应使函数名相同,而且函数的参数表也要相同,如果不相同,就成为函数的重载了。
(3)在声明派生类时增加的成员。我们要仔细考虑应当增加哪些成员,精心设计。
此外,在声明派生类时,一般还应当自己定义派生类的构造函数和析构函数,因为构造函数和析构函数是不能从基类继承的。
3 基类成员在派生类中的访问属性
我先给出结论,在作细致的分析:
表3.1 基类成员在派生类中的访问属性
在基类的访问属性 | 继承方式 | 派生类中的访问属性 |
private | public | 不可访问 |
private | private | 不可访问 |
private | protected | 不可访问 |
public | public | public |
public | private | private |
public | protected | protected |
protected | public | protected |
protected | private | private |
protected | protected | protected |
类成员的访问属性一共分为4中:
①public:类内类外都可以访问。
②protected:类内可以访问,类外不可以访问,下一层的派生类可以访问。
③private:类内可以访问,类外不能访问。
④不可访问:类内类外都不能访问。
由以上表格可知:
(1)当继承方式为public时,称为公用继承,用公用继承方式建立的派生类为公用派生类,其基类称为公用基类。采用公用继承方式时,基类的公用成员和保护成员在派生类中仍然保持其访问属性,而基类的私有成员却成为派生类中的不可访问的成员。那大家肯定就有疑问了,既然是公用继承,为什么不让访问基类的私有成员呢?因为私有成员体现了数据的封装性,隐藏私有成员有利于测试、调试和修改系统。如果派生类的成员能访问基类的私有成员,那派生类和基类就没有了界限了,这就破坏了基类的封装性。切记,保护私有成员是一条很重要的原则。对于基类的私有成员,在派生类中可通过调用基类的公用成员函数来引用。
(2)当继承方式为private时,基类的公用成员和保护成员成为了派生类的私有成员,即派生类的成员函数能访问它们,而在派生类外不能访问。基类的私有成员成了派生类中不可访问的成员,只有基类的成员函数可以引用它们。对于不需要再往下继承的类的功能可以用私有继承方式把它隐藏起来,这样,下一层的派生类无法访问它的任何成员。
(3)保护成员和保护继承
由protected声明的成员称为“保护成员”。受保护的成员不能被类外访问,从类的用户的角度来看,protected成员等价于private成员。但有一点不同,protected成员可以被派生类的成员函数引用。如果基类声明了私有成员,那么任何派生类都是不能访问它们的,若希望在派生类中能访问它们,则应该把它们声明为保护成员。一般地,如果你看到一个类中声明了保护成员,就意味着该类可能要用作基类,在它的派生类中会访问这些成员。
当继承方式为protected时,基类的公有成员和保护成员在派生类中都成了保护成员,其私有成员仍为基类私有。
以上介绍了只有一级派生的情况,实际上常常有多级派生的情况。无论哪一种继承方式,在派生类中是不能访问基类的私有成员的,私有成员只能被本类的成员函数所访问。如果在多级派生时都采用公用继承方式,那么直到最后一级派生类都能访问基类的公用成员和保护成员。如果采用私有的继承方式,经过若干次派生之后,基类的所有成员已经都变得不可访问了。如果采用保护继承方式,在派生类外是无法访问派生类中的任何成员的。在经过多次继承之后,很难记清楚那些成员可以访问,那些成员不可以访问,极易出错。因此,在实际中,常用的是公用继承。
(在本文中“公有”和“公用”同义)。