关闭

《程序员面试宝典》 —— 多态的作用

标签: C-C++
252人阅读 评论(0) 收藏 举报
分类:

   本文摘抄自《程序员面试宝典(第三版)》117~119页,为了便于自己理解,对某些表述做了修改。

   虚函数就是允许被其子类重新定义的成员函数。而子类重新定义父类虚函数的做法,称为“覆盖”(override),或者称为“重写”,覆盖的函数必须要与被覆盖函数有一致的参数列表和返回值。这里有一个初学者经常混淆的概念,即覆盖(override)和重载(overload)。覆盖是指派生类重新定义基类的虚函数的做法,而重载,是指允许存在多个同名函数,而这些函数的参数表不同(参数个数、参数类型、参数顺序不同,或者某些组合不同)。

   其实,重载的概念并不属于“面向对象编程”,重载的实现是编译器根据函数不同的参数列表,对同名函数的名称做修饰,然后这些同名函数就具有了不同的函数名(至少对于编译器来说是这样的)。如,有两个同名函数func(int p)和func(string p),那么经过编译器的修饰后,这两个函数名可能是int_func和str_func。对于这两个函数的调用,在编译期间就已经确定了,是静态的(记住:是静态)。也就是说,它们的地址在编译期间就绑定了(早绑定)。因此,重载和多态无关,它只是一种语法规则。

   真正与多态相关的是覆盖,父类指针是可以指向子类对象的,当子类重新定义了父类的虚函数后,父类指针根据赋给它的子类对象的不同,动态(注意:是动态)地调用属于子类的函数,这样的调用在编译期间是无法确定的(调用的具体的子类的虚函数地址无法给出),因此,这样的函数地址是在运行时绑定的(晚绑定)。

   结论就是,重载只是一种语言特性,与多态无关,也与面向对象无关。

   引用一句Bruce Eckel的话:“不要犯傻,如果它不是晚绑定,它就不是多态!”

   那么,多态的作用是什么呢?我们知道,封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类)。它们的目的都是为了代码重用,而多态则是为了实现另一个目的——接口重用。而且系那是往往是,要有效重用代码很难,而真正最具有价值的重用是接口重用,因为“接口是公司最有价值的资源。设计接口比用一堆类来实现这个接口更费时间,而且接口需要耗费更昂贵的人力和时间。”其实,继承为重用代码而存在的理由已经越来越薄弱,因为“组合”可以很好地取代继承的扩展现有代码的功能,而且“组合”的表现更好(至少可以防止“类爆炸”)。因此笔者个人认为,继承的存在很大程度上是作为“多态”的基础而非扩展现有代码的方式。

   多态性是面向对象最重要的特性。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:13558次
    • 积分:401
    • 等级:
    • 排名:千里之外
    • 原创:21篇
    • 转载:7篇
    • 译文:1篇
    • 评论:0条
    文章分类