为什么要使用多态

 

    引入多态是为了解决一般化问题和架构的抽象。

Ø       非多态的特点

1)       如果你以一个「基础类别之指针」指向「衍生类别之对象」,那么经由该指针你只能够调用基础类别所定义的函数。

2)       如果你以一个「衍生类别之指针」指向一个「基础类别之对象」,你必须先做明显的转型动作(explicit cast)。这种作法很危险,不符合真实生活经验,在程序设计上也会带给程序员困惑。另外,子类对象要调用父类别的函数,你必须使用scope resolution operator::)明白指出。

3)       如果基础类别和衍生类别都定义了「相同名称之成员函数」,那么透过对象指针调用成员函数时,到底调用到哪一个函数,必须视该指针的原始型别而定,而不是视指针实际所指之对象的型别而定。这与第1 点其实意义相通。

举例来讲,CAnimalCMonkey都具有Roar()函数,但是pAnimal=CAnimal*pMonkey pAnimal-> Roar()实际上调用的是CAnimal:: Roar(),在一般化处理时这并非程序员的期望。当然,还可以使用pAnimal -> CMonkey::Roar()明白指出调用哪一个函数,但程序就不再那么优雅与弹性了。

 

Ø       多态的解决方式

上述问题可以使用多态实现。实现多态的关键是虚拟函数,什么是虚拟函数呢?如果你预期衍生类别有可能重新定义某一个成员函数,那么你就在基础类别中把此函数设为virtual

Class CAnimal   {   Virtual Roar(){};   }

使用虚拟函数之后,我们以相同的指令却唤起了不同的函数,这种性质称为Polymorphism,意思是"theability to assume many forms"(多态)。其原理就是编译器无法在编译时期判断pAnimal-> Roar()到底是调用哪一个函数,必须在执行时期才能评估之,这称为后期绑定late binding 或动态绑定dynamic binding。至于C 函数或C++ non-virtual 函数,在编译时期就转换为一个固定地址的调用了,这称为前期绑定early binding 或静态绑定static binding

多态比较彻底的使用方式是采用纯虚拟函数,这样类就为抽象类,不能生成对象、很安全。关于抽象类别,我还有一点补充。CMonkey继承了CAnimal之后,如果没有改写CAnimal中的纯虚拟函数,那么CMonkey本身也就成为一个拥有纯虚拟函数的类别,于是它也是一个抽象类别。

 

Ø       小节

1)       如果你期望衍生类别重新定义一个成员函数,那么你应该在基础类别中把此函数设为virtual

2)       以单一指令唤起不同函数,这种性质称为Polymorphism,意思是"the ability toassume many forms",也就是多态。

3)       虚拟函数是C++ 语言的Polymorphism 性质以及动态绑定的关键。

4)       既然抽象类别中的虚拟函数不打算被调用,我们就不应该定义它,应该把它设为纯虚拟函数(在函数声明之后加上"=0" 即可)。

5)       我们可以说,拥有纯虚拟函数者为抽象类别(abstract Class),以别于所谓的具象类别(concrete class)

6)       抽象类别不能产生出对象实体,但是我们可以拥有指向抽象类别之指针,以便于操作抽象类别的各个衍生类别。

7)       虚拟函数衍生下去仍为虚拟函数,而且可以省略virtual 关键词。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值