按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
72
…………………………………………………………Page 135……………………………………………………………
#0025 //……………………………………………………………………………………………………………………………
#0026 class CRect : public CShape
#0027 {
#0028 public:
#0029 virtual void display() { cout display(); // 此进程序代码执行了6 次。
我们看到了一种奇特现象:程序代码完全一样(因为一般化了),执行结果却不相同。这
就是虚拟函数的妙用。
scope resolution operator ::
如果没有虚拟函数这种东西,你还是可以使用 明白指出调用
哪一个函数,但程序就不再那么优雅与弹性了。
从操作型定义来看,什么是虚拟函数呢?如果你预期衍生类别有可能重新定义某一个成
员函数,那么你就在基础类别中把此函数设为virtual 。MFC 有两个十分十分重要的虚
拟函数:与document 有关的Serialize 函数和与view 有关的OnDraw 函数。你应该在
CMyDoc CMyView
自己的 和 中改写这两个虚拟函数。
74
…………………………………………………………Page 137……………………………………………………………
多态 ( )
Polymorphism
你看,我们以相同的指令却唤起了不同的函数,这种性质称为Polymorphism ,意思是〃the
ability to assume many forms〃 pE mp …》put ePay
(多态)。编译器无法在编译时期判断
到底是调用哪一个函数,必须在执行时期才能评估之,这称为后期绑定late binding 或动
dynamic binding C C++ non…virtual
态绑定 。至于 函数或 的 函数,在编译时期就转换为
一个固定地址的调用了,这称为前期绑定early binding 或静态绑定static binding 。
Polymorphism 的目的,就是要让处理「基础类别之对象」的程序代码,能够完全透通地继
续适当处理「衍生类别之对象」。
可以说,虚拟函数是了解多态(Polymorphism )以及动态绑定的关键。同时,它也是了
解如何使用MFC 的关键。
让我再次提示你,当你设计一套类别,你并不知道使用者会衍生什么新的子类别出来。
如果动物世界中出现了新品种名曰雅虎,类别使用者势必在CAnimal 之下衍生一个
CYahoo 。饶是如此,身为基础类别设计者的你,可以利用虚拟函数的特性,将所有动物
必定会有的行为(例如哮叫roar ),规划为虚拟函数,并且规划一些一般化动作(例如
「让每一种动物发出一声哮叫」)。那么,虽然,你在设计基础类别以及这个一般化动
作时,无法掌握使用者自行衍生的子类别,但只要他改写了roar 这个虚拟函数,你的
一般化对象操作动作自然就可以调用到该函数。
再次回到前述的Shape 例子。我们说CShape 是抽象的,所以它根本不该有displ ay 这
个动作。但为了在各具象衍生类别中绘图,我们又不得不在基础类别CShape 加上
displ ay 虚拟函数。你可以定义它什么也不做(空函数):
class CShape
{
public:
virtual void display () { }
};
75
…………………………………………………………Page 138……………………………………………………………
或只是给个消息:
class CShape
{
public:
virtual void display () { cout