• 面试宝典之C++多态灵魂拷问


    🧸🧸🧸各位大佬大家好,我是猪皮兄弟🧸🧸🧸
    在这里插入图片描述

    一、重载,隐藏/重定义,覆盖/重写

    重载:同一作用域下的同名函数,需要返回值相同,参数列表不同构成重载

    重定义/隐藏:继承关系中,子类与父类有同名函数就构成隐藏,只要名字相同,就构成隐藏,同时,析构函数也是特殊的同名函数。因为多态的需要,编译器会把它同一处理为destructor

    重写:
    重写具有两个条件:一是该函数在父类是虚函数,二是函数相同(返回值,函数名,参数列表),但是对于返回值而言,有特例,叫做重写的协变,具体请看C++中的多态(上),满足以上两个条件就是重写,不满足函数三同,那么虚函数就按普通函数处理,如果虚函数不是拿来完成多态,纯纯资源浪费,因为会创建虚表指针和虚表。

    二、多态的原理

    多态的原理就是多态调用是运行时决议,虚函数会创建一个虚表指针指向虚表(这个虚表在常量区中,可以通过打印地址看到)多态调用就会去查找虚表中的对应函数。所以子类完成虚函数重写,那么就可以通过父类的指针/引用来完成多态。

    三、inline可以是虚函数吗

    内联函数是可以为虚函数的,如果内联不是虚函数,那么构成内联的条件的话,在预编译阶段就会展开,不会进符号表,所以在链接的时候找不到定义,所以把内联函数怕的就是这个。但是,inline是建议性的关键字,加了virtual之后,编译器就忽略掉了inline。

    四、静态成员函数可以是虚函数吗

    ①虚函数的调用过程:会先进入函数,因为虚函数是接口继承,所以父和子的接口都一样,随便进入一个,反正多态调用最后都会查虚表,该函数对应的虚表只有这一个,进入函数之后,通过this指针的方式,访问到虚表,从而进行调用,而静态成员函数的一大特点就是没有this指针,所以它也无法去通过多态调用。所以就算把静态成员函数存进虚表,也没有意义
    ②因为静态成员函数是可以通过指定类域的方式访问的 如A::func(); 说明它是编译时决议,你不管怎么多态,它在编译的时候就确定地址了,所以怎么也不会走到调用虚表这一地步。

    五、构造函数可以是虚函数吗

    ①首先,虚构造函数是没有意义的,因为构造函数的名字和类名相同,所以并不会发生重写,所以构造函数如果是虚函数,只会浪费空间
    ②虚函数表和虚函数指针是在构造函数的初始化列表进行初始化的,因为构造函数只会在对象创建的时候调用一次,如果你去调用虚构造函数,那么进入构造函数就会调用this,找到虚表指针去查虚表(虚表是编译阶段就确定了的,因为编译器通过识别virtual来创建虚表,存在常量区),但是此时构造函数都还没有构造,虚表指针都找不到
    所以构造函数不能是虚函数

    六、拷贝构造可以是虚函数吗

    ①第一点同上,没有意义,浪费资源
    ②第二点也同上,因为还没有拷贝构造好,你就要调用我的虚表指针,我找不到

    七、赋值运算符重载可以是虚函数吗

    因为如果已经到赋值运算符重载了,说明对象以及构造好了,所以赋值运算符重载可以是虚函数

    八、析构函数可以是虚函数吗

    析构函数需要定义成虚函数,这是因为避免内存泄漏。如果不定义成虚函数,那么A*a = new B/A&a = b;(b是new出来的),他们就只能析构父类的部分,而子类新开辟的空间就没有被释放掉,导致内存泄漏,编译器为了能让析构函数完成重写,函数名会同一处理成destructor,然后调用的时候,只需调用子类的析构就可以了(父类的析构会在子类的析构之后自动调用,细节见C++中的多态(上)

    在这里插入图片描述

  • 相关阅读:
    发明了杀毒软件之后,他选择做一个极品混混
    Python笔记 之 计算商品复购
    vue如何动态加载显示本地图片资源
    VSCode中打开md文件的智能提示
    【Java实现】合并两个有序链表
    深度剖析 Apache EventMesh 云原生分布式事件驱动架构
    【问题征集】向 iPod 之父、iPhone 联合设计者、Google Nest 创始人 Tony Fadell 提问啦
    Python 的运算符和语句(条件、循环、异常)基本使用指南
    item_search - 按关键字搜索EBAY商品
    5.jeecg的登录及权限(jwt+shiro)
  • 原文地址:https://blog.csdn.net/zhu_pi_xx/article/details/128060370