c++虚函数详解(多态特性)

1.c++多态的概念

多态是c++的特征之一

多态的分类:静态多态(静态联编)、动态多态(动态联编)

静态多态(静态联编):函数入口地址 是在 编译阶段 确定(运算符重载、函数重载)

动态多态(动态联编):函数入口地址 是在 运行阶段 确定(虚函数)

2.什么是向上类型转换

即:定义一个父类引用指针指向子类对象,通过父类指针或 引用来操作子类对象

示例代码如下:

#include <iostream>
using namespace std;

class Animal
{
public:
    void sleep(void)
    {
        cout<<"animal 动物在睡觉"<<endl;
    }
};

class Cat:public Animal
{
public:
    void sleep(void)
    {
        cout<<"Cat 猫在睡觉!! 喵喵"<<endl;
    }
};
int main()
{
    //用基类(指针或引用) 保存 子类对象(向上转换)
    Animal *p = new Cat;
    p‐>sleep();//调用的是基类的sleep

    Cat cat;
    Animal &ob = cat;
    ob.sleep();//调用的是基类的sleep
    return 0;
}

可见两次都是打印的基类中的sleep函数,而不是子类中的sleep函数。

 上图也解释了为什么只能打印基类中的sleep函数,因为这个基类指针(引用)只能操作Cat中的基类部分,而不能访问到Cat部分。

3.想用基类指针(引用)访问子类对象中的成员 要使用虚函数

虚函数允许子类重新定义父类中的成员函数,这种方法称为覆盖。即在父类中声明这个函数的时候

使用virtual关键字修饰。

如果一个函数在基类中被声明为 virtual,那么在所有派生类中它都是 virtual 的.

#include <iostream>

using namespace std;
class Animal
{
public:
    //虚函数 本质 是一个函数指针变量
    virtual void sleep(void)
    {
        cout<<"animal 动物在睡觉"<<endl;
    }
};
class Cat:public Animal
{
public:
    virtual void sleep(void)
    {
        cout<<"猫在睡觉!!喵喵"<<endl;
    }
};
int main()
{
    Animal *p = new Cat;
    p‐>sleep();//调用的是cat中sleep
    return 0;
}

 这样就能访问父类中的sleep函数。原因如下:

当一个基类中有虚函数时,里面会产生虚指针,同时会产生一个虚函数表

没有涉及到继承的时候,虚函数表里面存储的就是当前类里的虚函数入口地址;

当涉及到继承时,子类会继承父类中的虚指针和虚函数表编译器会自动将子类中的虚函数放入虚函数表中,于是这个虚指针遍历虚函数表时,拿到的就是子类中的虚函数地址;

上图中定义了基类指针 Animal *p = new Cat,然后p‐>sleep()调用函数,此时p的访问也是没有越界的,访问的仍然是Cat中的基类部分,只不过此时虚函数表中保存的是子类sleep函数地址,所以访问的是子类sleep函数。

  • :C++的动态捆绑机制是怎么样的?

首先,我们看看编译器如何处理虚函数。 当编译器发现我们的类中有虚函数的时候,编译器会

创建一张虚函数表,把虚函数 的函数入口地址放到虚函数表中,并在类中秘密增加一个虚指针,

这个指针就是 vpointer(缩写 vptr),这个指针是指向对象的虚函数表。在多态调用的时候,根据 

vptr指针,找到虚函数表来实现动态绑定。

4.虚函数的应用案例(基类指针、引用 作为函数的参数)

 示例代码:

#include <iostream>

using namespace std;
class Base
{
public:
    //虚函数 本质 是一个函数指针变量
    virtual void sleep()
    {
        cout<<"父亲在睡觉"<<endl;
    }
};
class Son1:public Base
{
public:
    void sleep()
    {
        cout<<"Son1在安静睡觉"<<endl;
    }
};
class Son2:public Base
{
public:
    void sleep()
    {
        cout<<"Son2在轻度睡觉"<<endl;
    }
};
class Son3:public Base
{
public:
    void sleep()
    {
        cout<<"Son3在雨声睡觉"<<endl;
    }
};
class Son4:public Base
{
public:
    void sleep()
    {
        cout<<"Son4在鼾声如雷睡觉"<<endl;
    }
};
//以基类指针作为函数参数 函数就可以操作所有子类
void sleepFun(Base &ob)
{
    ob.sleep();
}

int main(int argc, char *argv[])
{
    Son1 ob1;    //初始化子类对象
    Son2 ob2;
    Son3 ob3;
    Son4 ob4;
    sleepFun(ob1);
    sleepFun(ob2);
    sleepFun(ob3);
    sleepFun(ob4);
    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用go语言构建区块链 Part4.事务1

英文源地址 简介 事务是比特币的核心, 区块链的唯一目的是以安全可靠的方式存储交易, 因此在交易创建后没有人可以修改. 今天我们开始实现事务, 但由于这是一个相当大的主题, 我将它分成两部分: 在这一部分中, 我们将实现事务的通用机制, 在第二部分中, 我们将研究细节. 此外…

【Go语言从入门到实战】基础篇

Go语言从入门到实战 — 基础篇 First Go Program 编译 & 运行 基本程序结构 应用程序入口 package mainimport "fmt"func main() {fmt.Println("Hello World") }退出返回值 package mainimport ("fmt""os" )func main() {fmt.Pr…

Unity3D :使用 UXML 实例作为模板

推荐&#xff1a;将 NSDT场景编辑器 加入你的3D工具链 3D工具集&#xff1a; NSDT简石数字孪生 使用 UXML 实例作为模板 您可以将现有 UXML 文档实例化为 UXML 文档中的模板作为模板实例&#xff0c;类似于预制件 在 Unity 中工作。 使用 UXML 文档作为模板 要将项目中的现有…

MySQL高级篇——覆盖索引、前缀索引、索引下推、SQL优化、主键设计

导航&#xff1a; 【Java笔记踩坑汇总】Java基础进阶JavaWebSSMSpringBoot瑞吉外卖SpringCloud黑马旅游谷粒商城学成在线MySQL高级篇设计模式牛客面试题 目录 8. 优先考虑覆盖索引 8.1 什么是覆盖索引&#xff1f; 8.1.0 概念 8.0.1 覆盖索引情况下&#xff0c;“不等于”…

Fourier分析入门——第4章——频率域

目录 第 4 章 频率域(The Frequency Domain) 4.1 频谱分析(Spectral Analysis) 4.2 物理单位(Physics units) 4.3 笛卡尔坐标形式与极坐标形式对比 4.4 频谱分析的复数形式 4.5 复数值Fourier系数 4.6 复数值的和三角的Fourier系数之间的关系 4.7 2维或多维离散Fouri…

内容好但流量差?B站流量密码可能就在这

B站知名数码UP主老师好我叫何同学&#xff08;以下简称“何同学”。&#xff09;时隔两个月再次更新&#xff0c;这支标题为《为了找到流量密码&#xff0c;我们做了个假B站...》的视频不仅吸引了观众的围观&#xff0c;更是获得了众多B站UP主们的“声援”。 如题所见&#xf…

K8s in Action 阅读笔记——【3】Pods: running containers in Kubernetes

K8s in Action 阅读笔记——【3】Pods: running containers in Kubernetes 3.1 Introducing pods 在Kubernetes中&#xff0c;Pod是基本构建块之一&#xff0c;由容器集合组成。与独立部署容器不同&#xff0c;你总是要部署和操作一个Pod。Pod并不总是包含多个容器&#xff0…

如何高效地在网上找开源项目

开源项目是发展技能、分享想法和成为开发社区一员的好方法。开源意味着软件功能背后的源代码与所有想要阅读它的人公开共享。这意味着你可以准确地看到一个系统是如何工作的——一旦你愿意冒险&#xff0c;就为它做出贡献。除了向所有人开放贡献外&#xff0c;这种开放代码库通…

经典JavaScript手写面试题和答案

文章目录 实现一个函数去重&#xff1f;实现一个函数&#xff0c;判断指定元素在数组中是否存在&#xff1f;实现一个函数&#xff0c;将给定字符串反转&#xff1f;实现一个函数&#xff0c;检测指定字符串是否为回文&#xff08;即从前往后和从后往前的字符序列都相同&#x…

Systrace系列4 —— SystemServer 解读

本文主要是对 SystemServer 进行简单介绍,介绍了 SystemServer 中几个比较重要的线程,由于 Input 和 Binder 比较重要,所以单独拿出来讲,在这里就没有再涉及到。 窗口动画 Systrace 中的 SystemServer 一个比较重要的地方就是窗口动画,由于窗口归 SystemServer 来管,那么…

react学习3 生命周期

componentDidMount()与render()一个级别的&#xff0c;在组件挂载完成之后调用 卸载组件&#xff1a;REACTDOM.unmountComponentAtNode() componentWillUnmount() 组件马上被卸载的时候 老生命周期&#xff1a; 新的生命周期&#xff1a; 废弃了&#xff08;加上Unsate_还是…

RabbitMQ --- 死信交换机(一)

前言 当我们在使用消息队列时&#xff0c;难免会遇到一些消息被拒绝&#xff0c;重复投递或者超时等异常情况。这些异常消息如果不被正确处理&#xff0c;将会阻碍整个消息系统的正常运行。而此时&#xff0c;死信交换机&#xff08;Dead Letter Exchange&#xff0c;简称DLX&…

FAT NTFS Ext3文件系统有什么区别

10 年前 FAT 文件系统还是常见的格式&#xff0c;而现在 Windows 上主要是 NTFS&#xff0c;Linux 上主要是Ext3、Ext4 文件系统。关于这块知识&#xff0c;一般资料只会从支持的磁盘大小、数据保护、文件名等各种维度帮你比较&#xff0c;但是最本质的内容却被一笔带过。它们最…

MySQL-索引(2)

本文主要讲解MySQL-索引相关的知识点 联合索引前缀索引覆盖索引索引下推索引的优缺点什么时候适合创建索引,什么时候不适合?如何优化索引 ? 索引失效场景 ? 为什么SQL语句使用了索引,却还是慢查询 ? 使用索引有哪些注意事项 ? InnoDB引擎中的索引策略 目录 联合索引 联合…

【C++】函数重载 - 给代码增添多彩的魔法

欢迎来到博主 Apeiron 的博客&#xff0c;祝您旅程愉快 &#xff01; 时止则止&#xff0c;时行则行。动静不失其时&#xff0c;其道光明。 目录 1、缘起 2、函数重载概述 3、函数重载注意事项 4、总结 1、缘起 函数重载&#xff0c;是编程世界中的一抹迷人色彩&#xff0c…

动态规划-状态压缩DP

[SCOI2005] 互不侵犯 题目描述 https://www.luogu.com.cn/problem/P1896 在NN的棋盘里面放K个国王&#xff0c;使他们互不攻击&#xff0c;共有多少种摆放方案。国王能攻击到它上下左右&#xff0c;以及左上左下右上右下八个方向上附近的各一个格子&#xff0c;共8个格子。 …

堪比ChatGPT,Claude注册和使用教程

新建了一个网站 https://ai.weoknow.com/ 每天给大家更新可用的国内可用chatGPT资源 Claude简介 Claude是一款人工智能聊天机器人。主要有以下特征: 使用自己的模型与训练方法,而不是基于GPT-3等开源框架。模型采用Transformer编码器与解码器的结构,并使用对话上下文的双向…

实验六 自动驾驶建模与仿真

【实验目的】 了解Matlab/Simulink软件环境&#xff0c;熟悉Simulink建模步骤&#xff1b;了解车辆运动控制的基本原理&#xff0c;学会简单的车辆运动控制建模及仿真&#xff1b;了解自动驾驶建模的基本过程&#xff0c;了解典型ADAS系统模型的应用特点。了解自动驾驶相关函数…

老司机解读香农定理、奈奎斯特定理、编码与调制

工程师都会考虑一个问题&#xff1a;信道上到底可以传输多大的数据&#xff0c;或者指定的信道上的极限传输率是多少。这就是信道容量的问题。例如&#xff0c;在xDSL系统中&#xff0c;我们使用的传输介质是仅有几兆带宽的电话线&#xff0c;而上面要传送几兆、十几兆甚至几十…

用 Python 写 3D 游戏

vizard介绍 Vizard是一款虚拟现实开发平台软件&#xff0c;从开发至今已走过十个年头。它基于C/C&#xff0c;运用新近OpenGL拓展模块开发出的高性能图形引擎。当运用Python语言执行开发时&#xff0c;Vizard同时自动将编写的程式转换为字节码抽象层(LAXMI)&#xff0c;进而运行…