有一种普遍的说法是把封装、继承和多态并称为面向对象的三大特征。如果你很熟悉C++并且对面向对象思想有过一些思考,那么很可能对这个说法有过怀疑,面向对象思想在本质上认为世界是由对象构成的,和面向过程是世界观的不同,而所谓的三大特征实际和面向对象的思想本质没有半毛钱的关系,准确的表述应该是封装、继承和多态是C++相对于C的三大特征。如果你碰巧了解一点C++编译器可能会发现封装也好,继承、多态也好都只是语法糖,技巧层面的东西而已,和思想无关。
以上为废话。
本文主要就C++的继承机制进行一些讨论。很多C++教材在讲到继承时喜欢利用几何上的一些概念,比如对如下的集合关系进行建模:

在一次内部技术培训的时候我提出这个问题,结果大家都沉默不语,于是我特意找了个新手程序员回答,他给出了我预料之中的答案:以四边形作为基类,矩形和正方形依次继承下来。没人表示同意也没人表示反对,可能所有的人第一反应得出的都是这个方案,但老鸟程序员会马上察觉出其中的不妥,即使他给不出更好的方案。
实际上在没有给定需求场景的情况下你永远无法设计出一个类,更不要说设计一组类和这些类的层次关系。很多教材都有这个毛病,上来就设计Student、Teacher而没说要完成的功能是什么,即使是做了许多年C++之后再回过头来看那些例子还是晕忽忽的,何况初学者,——当然这也许仅仅是因为我自己太笨。
我们设定两个简单的需求取边长和计算面积,暂时不考虑继承关系而分别实现三个类,那么它们是下面这个样子的:
1 class Quadrangle
2 {
3 public:
4 int GetSideLength(int index);
5 int GetArea(void);
6
7 private:
8 int m_arrSlide[4];
9 };
10
11 class Rectangle
12 {
13 public:
14 int GetWidth(void);
15 int GetHeight(void);
16 int GetArea(void);
17
18 private:
19 int m_nWidth;
20 int m_nHeight;
21 };
22
23 class Square
24 {
25 public:
26 int GetWidth(void);
27 int GetArea(void);
28
29 private:
30 int m_nWidth;
31 };
显然,正方形四边形Square 的实现最简单,四边形Quadrangle的实现最复杂(知道四条边长能确定唯一的四边形吗?)。继承机制有一个特点:派生类总是比基类更复杂,因为派生类是在完整的继承了基类实现的基础上增加新的成员、方法。由四边形到矩形再到正方形却是越来越简单,这就形成了一个悖论,导致我们无法按照继承的层次描述三者的关系。
一个老到的程序员会告诉你最好分别实现三个类,不考虑三个者之间的关系,这在大部分场景中是可行的。如果确实需要描述三者之间的层次关系,我能想到的最好的方式是使用接口: