分享

C++多态的实现方式总结

 雪柳花明 2016-12-26

实现多态有两种方法:

1、覆盖

***********

覆盖是指子类重新定义父类的虚函数的做法。

2、重载

***********

重载是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。


分析:

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

重载是在同一个类中相同的返回类型和方法名,但是参数的个数和类型可以不同;而覆盖是在不同的类中。

其实,重载的概念并不属于面向对象编程,重载的实现是:编译器根据函数不同的参数表,对同名函数的名称做修饰,然后这些同名函数就成了不同的函数。

比如有下面两个同名函数:

  1. function func(p:integer):integer;  
  2. function func(p:string):integer;  

那么编译器做过修饰后的函数名称可能是这样的:int_func、str_func。

对于这两个函数的调用,在编译期间就已经确定了,是静态的,称为早期联编。因此重载和多态无关。

真正和多态相关的是覆盖。当子类重新定义了父类的虚函数后,父类指针根据赋值给它的不同的子类指针,动态的调用属于子类的该函数,这样函数调用在编译期间是无法确定的,这样的函数地址在运行期间绑定称为动态联编。

大笑不要犯傻,如果它不是晚绑定,它就不是多态。


多态机制深入:

虚函数在C++中的实现机制就是用虚表和虚指针。也就是每个类用了一个虚表,每个类的对象用了一个虚指针。具体的用法如下:

  1. class A  
  2. {public:  
  3.     virtual void f();  
  4.     virtual void g();  
  5. private:  
  6.     int a  
  7. };  
  8.   
  9. class B : public A  
  10. {  
  11. public:  
  12.     void g();  
  13. private:  
  14.     int b;  
  15. };//A、B实现省略  

因为A有virtual void f()和g(),所以编译器为A类准备了一个虚表vtableA,内容如下:

A::f 的地址
A::g 的地址



B因为继承了A,所以编译器也为B准备了一个虚表vtableB,内容如下:

A::f 的地址
B::g 的地址


注意:因为B::g是重写了的,所以B的虚表的g放的是B::g的入口地址,但是f是从上面的A继承下来的,所以f的地址是A::f的入口地址。然后某处有语句 B bB;的时候,编译器分配空间时,除了A的int a,B的成员int b;以外,还分配了一个虚指针vptr,指向B的虚表vtableB,bB的布局如下:

vptr : 指向B的虚表vtableB

int a: 继承A的成员

int b: B成员



关于虚函数下面的讲解下面博客总结的也很好:

点击打开链接



参考维基百科补充些多态的知识:

多态是指计算机程序运行时,相同的消息可能会送给多个不同的类之对象,而系统可依据对象所属类,引发对应类的方法,而有不同的行为。简单来说,所谓多态意指相同的消息给予不同的对象会引发不同的动作称之。


多态可分为变量多态与函数多态。变量多态是指:基类型的变量(对于C++是引用或指针)可以被赋值基类型对象,也可以被赋值派生类型的对象。函数多态是指,相同的函数调用界面(函数名与实参表),传送给一个对象变量,可以有不同的行为,这视该对象变量所指向的对象类型而定。因此,变量多态是函数多态的基础。


多态还可分为:
*************
动态多态:通过类继承机制和虚函数机制生效于运行期。可以优雅地处理异质对象集合,只要其共同的基类定义了虚函数的接口。在面向对象程序设计中,这被直接称为多态。
*************
静态多态:模板也允许将不同的特殊行为和单个泛化记号相关联,由于这种关联处理于编译期而非运行期,因此被称为“静态”。可以用来实现类型安全、运行高效的同质对象集合操作。C++ STL不采用动态多态来实现就是个例子。
*************
非参数化多态:
函数重载;运算符重载;带变量的宏多态
*************
参数化多态:把类型作为参数的多态。在面向对象程序设计中,这被称作泛型编程。

***********************************************************************************************************
对于C++语言,带变量的宏和函数重载机制也允许将不同的特殊行为和单个泛化记号相关联。然而,习惯上并不将这种函数多态、宏多态展现出来的行为称为多态(或静态多态),否则就连C语言也具有宏多态了。谈及多态时,默认就是指动态多态,而静态多态则是指基于模板的多态。


最后来举个例子:

比如有动物(Animal)之类(Class),而且由动物继承出类鸡(Chicken)和类狗(Dog),并对同一源自类动物(父类)之一消息有不同的响应,如类动物有“叫()”之动作,而类鸡会“啼叫()”,类狗则会“吠叫()”,则称之为多态。


哈哈~~~~~~~~~~~~~~~~

这下该对多态有个很好的认识了吧!!!!!!!!!!!!!!

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多