多态中虚函数的底层原理

2023-10-20 07:48

本文主要是介绍多态中虚函数的底层原理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

多态的基本概念 


 多态的实现当然离不开虚函数,有了虚函数才能有多态。

当定义了一个父类指针指向子类对象时,此时用通过父类指针访问子类中与父类里同名的一个函数时访问到的其实是父类的函数,因为在编译时就绑定好了父类的函数地址(因为是父类指针),而如何实现多态呢??那就需要动态绑定,也就是执行时再绑定函数地址,这时就需要虚函数了。

创建了虚函数后,子类继承父类时还多继承了一个虚函数指针以及虚函数表,当重写父类函数后,虚函数表中的函数地址(父类)会被覆盖为子类的重写函数,同时父类该函数的所有重载版本都会被隐藏,只有通过域名进行访问。

class Animal
{
public://虚函数virtual void speak(){cout << "动物在说话" << endl;}virtual void eat(int a ){cout << "动物在吃饭" << endl;}
};class Cat :public Animal
{
public:void speak(){cout << "小猫在说话" << endl;}void eat(int a){cout << "小猫在吃饭" << endl;}
};class Dog :public Animal
{
public:void speak(){cout << "小狗在说话" << endl;}
};//动态多态产生条件:
//先有继承关系
//父类中有虚函数,子类重写父类中的虚函数
//父类的指针或引用  指向子类的对象//对于有父子关系的两个类  指针或者引用 是可以直接转换的
void doSpeak(Animal & animal) //Animal & animal = cat;
{//如果地址早就绑定好了,地址早绑定,属于静态联编//如果想调用小猫说话,这个时候函数的地址就不能早就绑定好,而是在运行阶段再去绑定函数地址,属于地址晚绑定,叫动态联编animal.speak(); }void test01()
{Cat cat;doSpeak(cat);Dog dog;doSpeak(dog);
}void test02()
{//cout << "sizeof  Animal = " << sizeof (Animal) << endl;Animal * animal = new Cat;//animal->speak();// *(int *)animal 解引用到虚函数表中// *(int *)*(int *)animal 解引用到函数speak地址//调用猫说话((void(*)()) (*(int *)*(int *)animal)) ();//C/C++默认调用惯例  __cdecl//用下列调用时候 真实调用惯例  是 __stdcall                //调用猫吃饭typedef void( __stdcall *FUNPOINT)(int);(FUNPOINT (*((int*)*(int*)animal + 1)))(10);
}

虚函数指针以及虚函数表

 

用指针模拟对虚函数表中函数地址的访问实现

 希望对各位小伙伴有所帮助!

如有问题请发表在评论区!大家共同讨论!

 

这篇关于多态中虚函数的底层原理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/245712

相关文章

C/C++错误信息处理的常见方法及函数

《C/C++错误信息处理的常见方法及函数》C/C++是两种广泛使用的编程语言,特别是在系统编程、嵌入式开发以及高性能计算领域,:本文主要介绍C/C++错误信息处理的常见方法及函数,文中通过代码介绍... 目录前言1. errno 和 perror()示例:2. strerror()示例:3. perror(

Java编译生成多个.class文件的原理和作用

《Java编译生成多个.class文件的原理和作用》作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象... 目录一、内部类机制与.class文件生成成员内部类(常规内部类)局部内部类(方法内部类)匿名内部类二、

Kotlin 作用域函数apply、let、run、with、also使用指南

《Kotlin作用域函数apply、let、run、with、also使用指南》在Kotlin开发中,作用域函数(ScopeFunctions)是一组能让代码更简洁、更函数式的高阶函数,本文将... 目录一、引言:为什么需要作用域函数?二、作用域函China编程数详解1. apply:对象配置的 “流式构建器”最

Python中随机休眠技术原理与应用详解

《Python中随机休眠技术原理与应用详解》在编程中,让程序暂停执行特定时间是常见需求,当需要引入不确定性时,随机休眠就成为关键技巧,下面我们就来看看Python中随机休眠技术的具体实现与应用吧... 目录引言一、实现原理与基础方法1.1 核心函数解析1.2 基础实现模板1.3 整数版实现二、典型应用场景2

Java的IO模型、Netty原理解析

《Java的IO模型、Netty原理解析》Java的I/O是以流的方式进行数据输入输出的,Java的类库涉及很多领域的IO内容:标准的输入输出,文件的操作、网络上的数据传输流、字符串流、对象流等,这篇... 目录1.什么是IO2.同步与异步、阻塞与非阻塞3.三种IO模型BIO(blocking I/O)NI

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda

C++中::SHCreateDirectoryEx函数使用方法

《C++中::SHCreateDirectoryEx函数使用方法》::SHCreateDirectoryEx用于创建多级目录,类似于mkdir-p命令,本文主要介绍了C++中::SHCreateDir... 目录1. 函数原型与依赖项2. 基本使用示例示例 1:创建单层目录示例 2:创建多级目录3. 关键注

C++中函数模板与类模板的简单使用及区别介绍

《C++中函数模板与类模板的简单使用及区别介绍》这篇文章介绍了C++中的模板机制,包括函数模板和类模板的概念、语法和实际应用,函数模板通过类型参数实现泛型操作,而类模板允许创建可处理多种数据类型的类,... 目录一、函数模板定义语法真实示例二、类模板三、关键区别四、注意事项 ‌在C++中,模板是实现泛型编程

kotlin的函数forEach示例详解

《kotlin的函数forEach示例详解》在Kotlin中,forEach是一个高阶函数,用于遍历集合中的每个元素并对其执行指定的操作,它的核心特点是简洁、函数式,适用于需要遍历集合且无需返回值的场... 目录一、基本用法1️⃣ 遍历集合2️⃣ 遍历数组3️⃣ 遍历 Map二、与 for 循环的区别三、高

C语言字符函数和字符串函数示例详解

《C语言字符函数和字符串函数示例详解》本文详细介绍了C语言中字符分类函数、字符转换函数及字符串操作函数的使用方法,并通过示例代码展示了如何实现这些功能,通过这些内容,读者可以深入理解并掌握C语言中的字... 目录一、字符分类函数二、字符转换函数三、strlen的使用和模拟实现3.1strlen函数3.2st