Effective C++ 学习笔记(26)
2011-08-07 18:27 Daniel Zheng 阅读(186) 评论(0) 编辑 收藏 举报说你想说的;理解你所说的
在本章关于 "继承和面向对象设计" 的简介中,我曾强调,理解不同的面向对象构件在C++中的含义十分重要。这和仅仅知道C++语言的规则有很大的不同。例如,C++规则说,如果类D 从类B 公有继承,从D 的指针到B 的指针就有一个标准转换;B 的公有成员函数将被继承为D 的公有成员函数,等等。这些规则都是正确的,但在将设计思想转化为C++的过程中,它们起不到任何作用。相反,你需要知道,公有继承意味着 "是一个",如果D 从B 公有继承,类型D 的每一个对象也 "是一个" 类型B 的对象。因而,如果想在设计中表示 "是一个",就自然会想到使用公有继承。
"说出你想说的" 只是成功的一半。事情的另一面是 "理解你所说的",这一点同样重要。例如,将成员函数声明为非虚函数会给子类带来限制,如果没有认识到这一点就随便这样做将是不负责任的行为 ---- 除非你完全是有意这么做。声明一个非虚成员函数,你实际上是在说这个函数表示了一种特殊性上的不变性;如果不明白这一点,将会给程序带来灾难。
公有继承和 "是一个" 的等价性,以及非虚成员函数和 "特殊性上的不变性" 的等价性,是C++构件如何和设计思想相对应的例子。下面的列表总结了这些对应关系中最重要的几个。
共同的基类意味着共同的特性。如果类 D1 和类D2 都把类B 声明为基类,D1 和D2 将从B 继承共同的数据成员和/或共同的成员函数。
公有继承意味着 "是一个"。如果类D 公有继承于类B,类型D 的每一个对象也是一个类型B 的对象,但反过来不成立。见条款35。私有继承意味着 "用...来实现"。如果类D 私有继承于类B,类型D 的对象只不过是用类型B 的对象来实现而已;类型B 和类型D 的对象之间不存在概念上的关系。
分层意味着 "有一个" 或 "用...来实现"。如果类A 包含一个类型B 的数据成员,类型A 的对象要么具有一个类型为B 的部件,要么在实现中使用了类型B 的对象。
下面的对应关系只适用于公有继承的情况:
纯虚函数意味着仅仅继承函数的接口。如果类 C 声明了一个纯虚函数mf,C 的子类必须继承mf 的接口,C 的具体子类必须为之提供它们自己的实现。
简单虚函数意味着继承函数的接口加上一个缺省实现。如果类 C 声明了一个简单(非纯)虚函数mf,C 的子类必须继承mf 的接口;如果需要的话,还可以继承一个缺省实现。
非虚函数意味着继承函数的接口加上一个强制实现。如果类 C 声明了一个非虚函数mf,C 的子类必须同时继承mf 的接口和实现。实际上,mf 定义了C的 "特殊性上的不变性"。