前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++多态特性详解

C++多态特性详解

作者头像
咬咬
发布2024-06-12 14:14:01
740
发布2024-06-12 14:14:01
举报
文章被收录于专栏:学习笔记学习笔记

目录

概念:

定义及实现:

虚函数重写的两个例外:

1.协变:

2.析构函数的重写:

final关键字:

override关键字:

多态是如何实现的(底层):

面试题:


概念:

所谓多态就是,当去完成某个行为时,不同的对象会产生不同的状态,导致不同的结果。

举个简单的例子:当去一个景区旅游,成人买票是全价,儿童买票是半价,这就是一种典型的多态。还有个典型的例子:大家在使用某多多助力拿红包时,有的能拿到,有的却邀了几百个人还是拿不到,这可能就是一种多态,如果你是新用户,它就会让你拿到,如果你是老用户,它可能让你拿不到。(仅个人猜测)

定义及实现:

c++中构成多态需要满足2个条件:

1.父类的指针或者引用去调用虚函数。 2.完成虚函数的重写,满足三同(函数名,返回值,参数)。

上述的三同有特例,后面会讲,我们先来简单实现一下上面买票这个例子的多态:

试试传子类的引用看看结果如何:

注意:虚函数不能写成全局的,只能写在类里面。虚函数和正常的成员函数一样都存在代码段。

虚函数重写的两个例外:

上面讲到了虚函数重写需要满足三同,函数名,返回值,形参都要保证和父类里面的对应虚函数相同,但也有两个例外。

1.协变:

子类重写父类虚函数时,与父类虚函数返回值类型不同。即父类虚函数返回父类对象的指针或者引用,子类虚函数返回子类对象的指针或者引用时,称为协变。(基类与派生类虚函数返回值类型不同)

不一定返回自己的父类或者子类,别的父类或者子类也可以:

2.析构函数的重写:

如果父类的析构函数为虚函数,此时子类析构函数只要定义,无论是否加virtual关键字, 都与父类的析构函数构成重写,虽然基类与派生类析构函数名字不同。虽然函数名不相同, 看起来违背了重写的规则,其实不然,这里可以理解为编译器对析构函数的名称做了特殊处 理,编译后析构函数的名称统一处理成destructor。

看下面这个场景:

因为有切片的概念,父类的指针可以指向子类,注意看这里调用了两次父类的析构,但我们new出来的时一个父类和一个子类,这里看似没什么影响,但我们稍微对子类修改一下 :

这时如果不调用子类的析构就会造成内存泄漏,解决办法:

结论:建议将析构函数写成虚函数,防止内存泄漏。

final关键字:

当final修饰虚函数时,则改虚函数不能被重写:

当final修饰一个类时,这个类为最终类,无法被继承:

override关键字:

加到子类重写的虚函数检查是否完成重写:

多态是如何实现的(底层):

看下面这个场景

A里面明明只有一个变量_a,虚函数func是存在代码段的,没在类里面,按理来说应该算出4字节为何这里是16字节?

答:一旦类里面有虚函数,类的头4个(32位机器)或者8个(64位机器)字节就会有一个虚表指针 ,我这里是64位机器,然后又要满足结构体对齐,所以是16,我们用监视窗口看一下:

确实有个虚表指针,它指向该类虚函数的地址:

想必已经猜出来了,虚表指针,指向的就是该类中所有虚函数的起始地址。

相同类型的类共用一个虚表,也就是虚表指针是相同的。

当我们在子类对虚函数进行重写后,子类的虚表就存的是重写后的虚函数,父类的虚表存的还是重写前的虚函数,当我们用父类或者子类的引用或者指针去访问虚表时,就会访问到不同的虚表,从而完成不同的行为,构成多态。

那要是多继承,虚表指针是怎么存的呢?

再复杂点,多继承中的菱形继承又是怎么存虚表指针的呢?

此时D中的结构就如下图:

再再再复杂一点,多继承中的菱形虚拟继承又是怎么存虚表指针的?

此时D中的结构就如下图:

虚基表指针的知识我以后会讲 。

注意:虚表是存在常量区的,不是存在类里面,只是虚表指针存在类的头4个或者8个字节。

面试题:

该程序运行的结果是什么?

A: A->0 B: B->1 C: A->1 D: B->0 E: 编译出错 F: 以上都不正确 答案:B

因为虚函数的重写,重写的只是定义,它的形参的缺省值用的还是父类里面的。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-06-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概念:
  • 定义及实现:
  • 虚函数重写的两个例外:
    • 1.协变:
      • 2.析构函数的重写:
      • final关键字:
      • override关键字:
      • 多态是如何实现的(底层):
      • 面试题:
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档