C++的多态、虚函数、虚继承

1、C++多态

多态,从字面意思上来说就是同一个事物的多种形态。而在C++里面,多态分为静态多态和动态多态。静态多态主要的实现有函数的重载和模板,主要特点是在编译阶段,就能确定具体要调用的函数。动态多态主要是通过虚函数实现,它有个特点就是只有在运行阶段,才能确定具体的调用。
这里主要讲下动态多态。动态多态有两个条件,第一个是基类中必须有虚函数,而且子类必须对父类的虚函数进行重写。第二个条件是通过父类的指针调用子类的虚函数。
这里在重写时,重写的函数原型必须要和父类的一致,即参数列表和返回值类型要相同。但有个例外,当类中虚函数的返回值是自身的引用或指针时,这样的重写也成立,比如父类的虚函数返回值类型是父类的指针,子类的虚函数返回值类型是子类的指针,这样的重写也行。

2、虚函数

虚函数的的产生主要是为了实现多态性。在C++中,允许父类指针指向子类,那么当父类指针调用成员函数时,我希望被调用的函数由指向对象的具体类型来决定,为了实现这个,就需要用到虚函数了。
虚函数通过virtual关键字声明,而且必须是类的成员函数,不能是友元函数和全局函数(不是类成员函数),也不能是静态成员函数(它没有this指针),也不能是构造函数、拷贝构造函数等(具体为什么留到后面讲)。当一个父类指针调用虚函数时,首先通过隐式传入该函数的具体对象this指针找到虚表指针,在通过虚表指针找到虚函数表,虚函数表里就有具体要调用的虚函数地址。虚函数表是属于类的,子类继承父类时也会继承它的虚函数表,当重写虚函数时,就会用重写后的虚函数地址替换继承自父类虚表中的函数地址。
虚函数在声明的时候如果在后面加上=0,那么该函数就是纯虚函数,包含纯虚函数的类叫抽象类,抽象类不能构造对象,只能用来被继承。因为在抽象类的虚表中,纯虚函数的地址是等于0的,而普通的虚函数地址应该是个有意义的值。若是抽象类能构造对象,那调用纯虚函数时,就会发现地址没有意义。
最后一点就是当类中有虚函数时,析构函数最好也是虚函数,因为当子类重写虚函数时,可能会进行一些动态申请内存之类的操作,而释放内存,则需要调用子类的的析构函数实现。
补:构造函数不能是虚函数的原因:
1、 调用虚函数时,需要虚表指针,而虚表指针是调用构造函数后才建立。若构造函数是虚函数,那就会陷入一个先有鸡还是先有蛋的循环。获取虚函数指针需要对象构造完毕,而构造对象又需要虚函数指针。
2、 另一方面,在构造函数中也不能调用虚函数。因为在构造对象时,对象的类型还未确定,而虚函数是在运行时根据对象的类型类确定具体的调用。

3、虚继承

虚继承是为了解决子类通过不同路径继承到共同基类的问题而产生的。假如有个基类A,中间类B和中间类C都继承了类A,类D同时继承类B和类C。那么当类D的对象访问属于A的成员后,就会出现二义性错误。因为在D的对象的栈空间中,保留了两份基类A的成员。另一方面,当用A的指针指向D的对象时也会出错,因为指针想指向D类对象中属于A的部分,单A的部分有两个。
为了解决这种问题,就引入了虚继承,当B和C都虚继承A后,若D同时继承B和C,那么对于共同基类A,D的对象只会存储一份。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值