C++中的虚函数

news2024/11/20 3:33:28

一、虚函数 (类继承中的一种函数) 概念

概念

被virtual修饰的函数叫做虚函数。
为什么说虚函数是类继承中的一种函数呢? 因为虚函数的作用确实主要是在类的继承中体现的(即派生类和基类)
虚函数的作用就是当基类和派生类中都有一个同名字的函数。 当基类指针存放派生类对象的地址时。通过该指针访问同名成员函数的时候,会出现一下两种情况:
那到底是调用基类的还是调用派生类的呢?
.
.
如果该函数在基类中是虚函数:则调用派生类 — 这里就体现了虚函数能让基类类和派生类的成员函数突出独特性。
.
如果该函数在基类中不是虚函数:则调用基类。

例子

#include <iostream>

using namespace std;

class f
{
public:
    int f_data;
    f(int f_data = 10)
    {
        this->f_data = f_data;
    }
    virtual void display()
    {
        cout<<"我是基类的成员函数"<<f_data<<endl;
    }
};

class c : public f
{
public:
    int c_data;
    c(int c_data = 10)
    {
        this->c_data = c_data;
    }
     void display()
    {
        cout<<"我是pai派生类的成员函数"<<c_data<<endl;
    }
};

int main()
{
    //只需要定义一个派生类
    c c_1(9);

    f * f_p = &c_1;//定义一个基类存放派生类对象的地址

    f_p->display();//这个display是基类的还是派生类的? 如果display在基类中不是虚函数则调用基类的,如果是虚函数则调用派生类的
    return 0;
}

用virtual修饰(即基类中的是虚函数) 运行效果:
在这里插入图片描述

不用virtual修饰(即基类中的不是虚函数)运行效果:
在这里插入图片描述

注意

在基类用virtual声明成员函数为虚函数。
.
这样就可以在派生类中重新定义此函数,为它赋予新的功能,并能方便地被调用。在类外定义虚函数时,不必再加virtual。
.
在派生类中重新定义此函数,要求函数名、函数类型、函数参数个数和类型全部与基类的虚函数相同,并根据派生类的需要重新定义函数体。
.
C++规定,当一个成员函数被声明为虚函数后,其派生类中的同名函数都自动成为虚函数。因此在派生类重新声明该虚函数时,可以加virtual,也可以不加,但习惯上一般在每一层声明该函数时都加virtual,使程序更加清晰。
.
如果在派生类中没有对基类的虚函数重新定义,则派生类简单地继承其直接基类的虚函数。
.
定义一个指向基类对象的指针变量,并使它指向同一类族中需要调用该函数的对象。

二、类中的虚表中的虚函数

前置概念

只有类中有虚函数的前提下,在实例化类对象的时候才会生成虚表,虚表其实一个指针变量,这这个指针变量解引用之后得到一个地址,这个地址上存放了第一个虚函数的首地址(一级指针),则这个地址是二级指针变量的地址(三级指针),所以这个虚表指针变量只能是一个四级指针变量(四级针变量解引用才得到三级指针变量),而这个二级指针变量就是存放第一个虚函数的地址。如下图所示:
.
重要的概念:类对象的地址等于虚表的地址
有了虚表的存在,我们就可以通过类对象的地址调用虚表里面的虚函数
在这里插入图片描述

通过类对象输出虚表中的虚函数首地址以及通过虚函数指针调用虚函数

#include <iostream>

using namespace std;

class demo
{
public:

    virtual int Fun_1()
    {
        cout<<"我是第一个虚函数" <<endl;
        return 0;
    }

    virtual int Fun_2()
    {
        cout<<"我是第二个虚函数" <<endl;
        return 0;
    }
};


int main()
{
    class demo d_1;

    unsigned long long * p = (unsigned long long * )(*((unsigned long long * )(&d_1)));

    cout<<"这是存放第一个虚函数首地址的首地址:"<< p   <<endl;
    cout<<"这是存放第二个虚函数首地址的首地址:"<< p+1   <<endl;

    int(*v_p1)() = (int (*)())(*p);//就是第一个虚函数的函数地址

    int(*v_p2)() = (int (*)())(*(p+1));//就是第二个虚函数的函数地址


    return 0;
}

注意:指针解引用获取虚表和获取虚表元素的时候,因为虚表是没有类型的,所用需要把指针类型强转成 long long * int * *等等等,只要解引用能获取8个字节即可,因为解引用是获取地址一个地址一般是8个字节 。

运行效果如下:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/945797.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Verilog基础:巴科斯范式(BNF)

相关阅读 Verilog基础专栏https://blog.csdn.net/weixin_45791458/category_12263729.html?spm1001.2014.3001.5482 由于Verilog HDL标准中对语法的描述使用了Backus Naur Form&#xff08;BNF&#xff09;。本文将对其中的约定进行描述。 小写单词&#xff0c;其中一些包含…

安防监控/视频汇聚平台EasyCVR调用rtsp地址返回的IP不正确是什么原因?

安防监控/云存储/磁盘阵列存储/视频汇聚平台EasyCVR可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有GB28181、RTSP/Onvif、RTMP等&#xff0c;以及厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等&#xff0c;能对外分发RTSP、RT…

【记录】USSOCOM Urban3D 数据集读取与处理

Urban3D数据集内容简介 Urban3D数据集图像为正摄RGB影像&#xff0c;分辨率为50cm。 从SpaceNet上使用aws下载数据&#xff0c;文件夹结构为&#xff1a; |- 01-Provisional_Train|- GT|- GT中包含GTC&#xff0c;GTI&#xff0c;GTL.tif文件&#xff0c;GTL为ground truth b…

Linux学习之RAID

基础概念 RAID&#xff0c;英文全称为Redundant Arrays of Independent Drives&#xff0c;RAID&#xff0c;中文称为独立冗余磁盘阵列&#xff0c;这项技术把多个硬盘设备组合成一个容量更大的、安全性更好的磁盘阵列&#xff0c;把数据切割成许多区段分别放在不同的物理磁盘…

产品经理NPDP考什么?

一、准备阶段 敲黑板1&#xff1a;考试共200道单选&#xff0c;满分200&#xff0c;手填涂卡&#xff0c;150分通过。考试费3200。条件&#xff1a;2年以上工作经验。 敲黑板2&#xff0c;敲三下&#xff1a;备考宝典《产品经理 认证(NPDP)知识体系指南》——红宝书。 二、精…

C语言——程序执行的三大流程

顺序 : 从上向下&#xff0c; 顺序执行代码分支 : 根据条件判断&#xff0c; 决定执行代码的分支循环 : 让特定代码重复的执行

[FlareOn6]Snake 题解

这是是一个后缀为.nes的文件&#xff0c;NES&#xff08;Nintendo Entertainment System&#xff0c;任天堂娱乐系统&#xff09; 找到一个工具FCEUX可以打开和调试 打开十六进制编辑器观察数值的变化 发现0x25处记录了记录了吃掉苹果的个数 在这个地方打一个硬件断点 运行一…

新手入门吉他是要越贵越好吗?2023年最全面吉他选购指南,十大初学者吉他品牌推荐!【建议收藏】

全文10000字&#xff0c;本人亲测整理了一个多星期的成果&#xff0c;对比了市面上十多个吉他品牌、近50款初学者入门/进阶吉他的选材参数和销售数据&#xff0c;最终整理出的精华版&#xff0c;每个人都可以根据自己的预算找到合适的入门吉他产品。未经授权不得转载、引用、洗…

Python学习笔记:Requests库安装、通过url下载文件

1.下载安装requests库 在pipy或者github下载&#xff0c;通常是个zip&#xff0c;解压缩后在路径输入cmd&#xff0c;并运行以下代码 Python setup.py install 安装完成后&#xff0c;输入python再输入import requests得到可以判断时候完成安装 2.通过url下载文件 使用的是u…

谷歌浏览器调试技巧

一、概述 记录谷歌浏览器实用的调试技巧。 二、详解 技巧1&#xff1a;打开F12调试工具的前提下按下Ctrl Shift P 如下图所示&#xff0c;按下组合键&#xff0c;可打开命令面板。 技巧2&#xff1a;调试工具的Element面板下&#xff0c;按照Alt 鼠标左键可以将目标节点全部…

图解SQL查询之having

在 SQL 中&#xff0c;having 在分组聚合后进行条件筛选&#xff0c;保留满足特定条件的分组。与 where 的区别在于 where 在分组聚合前进行过滤。 以下是用到的表 例如要求出班级总年龄大于17的班级是哪些 注&#xff1a; 数据库服务器会自启 only_full_group_by 模式&#…

【LeetCode-中等题】98. 验证二叉搜索树

文章目录 题目方法一&#xff1a;BFS 层序遍历方法二&#xff1a; 题目 方法一&#xff1a;BFS 层序遍历 利用层序遍历 拿到每一个节点 并且给每一个结点配备一个最大值和最小值的队列 只要节点在最大值和最小值之间就满足二叉搜索树的条件 public boolean isValidBST(TreeNo…

2023 在Windows上的安装Faiss-GPU(使用anaconda)

该方法安装完 faiss-gpu 之后&#xff0c;不仅会装这个库&#xff0c;还会装很多依赖库。为了防止自己本地一些同名库的版本被修改&#xff0c;建议新建一个虚拟环境来安装。如果本地库版本修改对自己没影响&#xff0c;也可以忽略。 你好&#xff0c;我是悦创。 登录网站&…

Docker 的快速使用

ubuntu安装 centos安装 安装完毕之后执行一下这条命令&#xff0c;可以避免每次使用docker命令都需要sudo权限 sudo usermod -aG docker $USER阿里云docker镜像加速 DockerHub 遇到不懂或者不会使用的命令可以使用docker --help查看文档 docker --help 如&#xff1a; dock…

CSS按钮-跑马灯边框

思路很简单&#xff0c;实现方法有很多很多。但是大体思路与实现方法都类似&#xff1a;渐变色 动画&#xff0c;主要区别在动画的具体实现 0、HTML 结构 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><titl…

多线程网络实现在线聊天系统(详细源码)

这篇博客整理自韩顺平老师的多线程网络学习&#xff0c;在Java基础中最难的就是多线程以及网络编程了&#xff0c;如果不太熟悉的小伙伴可以跟着课程学习&#xff0c;韩老师讲得很详细&#xff0c;缺点就是太详细有点墨迹。实现后的效果是在一个类似命令行窗口进行聊天&#xf…

数论基础(II)。

数论基础&#xff08;II&#xff09;TOC 数论按照研究的数据、方法、方向不同&#xff0c;通常可以分为玄数论、素数论、和数论。无限个数&#xff0c;真正用得到的只有数头&#xff1b;数头比较重要的关限是100&#xff0c;120&#xff0c;十万&#xff0c;百亿&#xff0c;&…

【USRP】调制解调系列5:16QAM、32QAM、64QAM、256QAM、1024QAM、基于labview的实现

QAM 正交振幅键控是一种将两种调幅信号&#xff08;2ASK和2PSK&#xff09;汇合到一个信道的方法&#xff0c;因此会双倍扩展有效带宽&#xff0c;正交调幅被用于脉冲调幅。正交调幅信号有两个相同频率的载波&#xff0c;但是相位相差90度&#xff08;四分之一周期&#xff0c…

打造互动体验:品牌 DTC 如何转变其私域战略

越来越多的品牌公司选择采用DTC 模式与消费者进行互动&#xff0c;而非仅仅销售产品。通过与消费者建立紧密联系&#xff0c;DTC模式不仅可以提供更具成本效益的规模扩张方式&#xff0c;还能够控制品牌体验、获取宝贵的第一方数据并提升盈利能力。然而DTC模式的经济模型比许多…

嵌入式通用硬件模块设计——串口音频播放模块

模块功能展示&#xff1a; 串口音频控制模块 一、简介 方案为串口音频播放芯片功放芯片&#xff0c;口音频播放芯片IC为my1690-16s&#xff0c;功放为PAM8406。 1、my1690-16s 迈优科技的一款由串口控制的插卡MP3播放控制芯片&#xff0c;支持串口控制播放指定音频、音量调节…