第六章 继承和面向对象设计

优质
小牛编辑
126浏览
2023-12-01

第六章 继承和面向对象设计

很多人认为,继承是面向对象程序设计的全部。这个观点是否正确还有待争论,但本书其它章节的条款数量足以证明,在进行高效的C++程序设计时,还有更多的工具听你调遣,而不仅仅是简单地让一个类从另一个类继承。

然而,设计和实现类的层次结构与C语言中的一切都有着根本的不同。只有在继承和面向对象设计领域,你才最有可能从根本上重新思考软件系统构造的方法。另外,C++提供了多种很令人困惑的面向对象构造部件,包括公有、保护和私有基类;虚拟和非虚拟基类;虚拟和非虚拟成员函数。这些部件不仅互相之间有联系,还和C++的其它部分相互作用。所以,对于每种部件的含义、什么时候该用它们、怎样最好地和C++中非面向对象部分相结合 ---- 要想真正理解这些,就要付出艰苦的努力。

使得事情更趋复杂的另一个原因是,C++中很多不同的部件或多或少地好象都在做相同的事。例如:

· 假如需要设计一组具有共同特征的类,是该使用继承使得所有的类都派生于一个共同的基类呢,还是使用模板使得它们都从一个共同的代码框架中产生?

· 类A的实现要用到类B,是让A拥有一个类型为B的数据成员呢,还是让A私有继承于B?

· 假设想设计一个标准库中没有提供的、类型安全的同族容器类(条款49列出了标准库实际提供的容器类),是使用模板呢,还是最好为某个 "自身用普通(void*)指针来实现" 的类建立类型安全的接口呢?

在本章节的条款中,我将指导大家怎样去回答这类问题。当然,我不可能顾及到面向对象设计的方方面面。相反,我将集中解释的是:C++中不同的部件其真正含义是什么,当使用某个部件时你真正做了什么。例如,公有继承意味着 "是一个" (详见条款35),如果使它成为别的什么意思,就会带来麻烦。相似地,虚函数的含义是 "接口必须被继承",非虚函数的含义是 "接口和实现都要被继承"。不能区分它们之间的含义会给C++程序员带来无尽的痛苦。

如果能理解C++各种部件的含义,你将发现自己对面向对象设计的认识大大转变。你将不再停留在为区分C++语言提供的不同部件而苦恼,而是在思考要为你的软件系统做些什么。一旦知道自己想做什么,将它转化为相应的C++部件将是一件很容易的事。

做你想做的,理解你所做的!这两点的重要性绝没有过分抬高。接下来的条款将对如何高效地实现这两点进行了详细的讨论。条款44总结了C++面向对象构造部件间的对应关系和它们的含义。它是本章节最好的总结,也可作为将来使用的简明参考。