C++中的多态特性总结

一、分类:

1、静态多态:在编译时完成,例如:函数重载,泛型编程。

2、动态多态:程序执行期间,例如:虚函数{(1)一定要在派生类中对基函数进行重写。(2)基类的指针或引用调用虚函数}


二、虚函数:{virtual 返回值类型  函数名 (参数列表){}}

1、同名隐藏:如果基类与派生类具有相同的函数,则在调用函数时优先调用派生类的成员函数。

2、重写(覆盖):在继承体系中,如果基类中有虚函数,在派生类中有和基类虚函数原型完全相同的函数,则会发生函数重载。

    注:(1)若返回类型不同,则不能构成重写,但若都返回本类的指针或引用也可以构成重写。

            (2)析构函数也可以构成重写。【建议:最好将基类中析构函数写成虚函数】

3、纯虚函数:在成员函数的形参列表后面写上“=0”;

    virtual 返回值 函数名(参数列表)=0 {}

4、如果一个函数具有虚函数,则在内存中存放的时候会将前四个字节变成虚表指针,后面是成员变量。

虚表指针指向虚表,里面存放着虚函数地址。

5、虚函数的调用:

(1)取对象地址

(2)取对象的前4个字节的内容,-->虚表指针

(3)相对应的虚函数

6、虚函数的缺点:

(1)对象多了4个字节

(2)效率低

7、构造函数不能做虚函数:

    因为调用构造函数后才可以形成虚表以及虚表指针,如果将构造函数变成虚函数,则必须要先调用虚表才能调用构造函数,但因为没有调用构造函数就没有虚表,所以,构造函数就不能变成虚函数。

8、友元函数静态成员函数不能做虚函数:因为没有this指针。

总结:不同对象的虚表函数表不一样,所以实现了动态多态。


三、虚表(虚函数地址表)

1、基类中的虚函数按照按照在类中的声明次序,派生类中自己的虚函数则放在基类虚函数后,也按照顺序存放,如下图所示:

2、派生类:

(1)单继承:

a.检测基类中是否对基类虚函数进行重写,若重写则调用重写后的,反之,调用基类函数。

b.派生类中自己的虚函数在基类后,并按定义顺序放。

(2)多继承:

先继承的虚表在前,若派生类有单独的虚函数,则放在第一张虚表后。

3、总结虚拟机承德虚表格式:

四、几个小问题:

1、Base b1,b2,b3;    Derived d1,d2,d3;  

b1,b2,b3是否共用一张虚表?  共用

d1,d2,d3是否与b1,b2,b3共用一张虚表?  不共用

2、为什么下述代码会实现多态?

void Test(Base &b)

{b.Test();}

因为b是一个引用,所以会调用虚表

3、Base *pd=(Base*)&d1;(d1是派生类变量)调用谁的虚表?

答:调用的是派生类的虚表,因为d1里面的虚表指针指向的是派生类的虚表,尽管取得是Base类大小的空间但是虚表指针指向的是派生类的虚表指针,所以最终调用的是自己的虚表。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值