【什么是多态】从用c语言实现多态开始,解剖多态的核心

什么是多态性?

多态性源自希腊语,意为“多种形态”。在编程领域,多态性表示同一操作或消息可以应用于不同类型的对象,而产生不同的行为。这种行为基于对象的类型和方法的实现方式而异,但对于调用方来说,它们统一表现为同一种调用方式。

在C语言中模拟多态性

当我们谈到多态时,我们通常会想到面向对象编程中的概念。然而,C语言并不是一种面向对象的编程语言,因此它并没有提供内置的多态支持。然而,我们可以利用一些技巧来模拟多态性。我们可以定义一个结构体,其中包含对应于不同类型对象的函数指针。让我们通过一个简单的示例来说明

#include <stdio.h>// 声明动物结构体
typedef struct {void (*speak)();
} Animal;// 定义猫的功能
void catSpeak() {printf("喵喵!\n");
}// 定义狗的功能
void dogSpeak() {printf("汪汪!\n");
}int main() {// 创建猫对象Animal cat;cat.speak = catSpeak;// 创建狗对象Animal dog;dog.speak = dogSpeak;// 使用多态调用函数printf("猫说:");cat.speak();printf("狗说:");dog.speak();return 0;
}

在这个示例中,我们定义了一个Animal结构体,其中包含一个指向函数的指针speak。然后,我们定义了两个不同的函数catSpeakdogSpeak,分别对应猫和狗的行为。在main函数中,我们创建了一个猫对象和一个狗对象,并将相应的函数指针赋值给它们的speak成员。最后,通过多态性,我们调用了不同对象的speak函数,分别产生了不同的输出。

多态的核心原理

多态的实现基于两个重要概念:继承和动态绑定。

  1. 继承(Inheritance):继承是OOP中的基本机制,它允许新的类(子类)从现有类(父类)派生而来,并继承父类的属性和方法。子类可以重写(覆盖)父类的方法,以实现自己特定的行为。

  2. 动态绑定(Dynamic Binding):动态绑定是多态性的关键。它指的是在程序运行时(而不是编译时)确定要调用的方法。通过使用基类的指针或引用来调用派生类的方法,编译器能够根据实际对象的类型来动态地选择正确的方法。

多态的实现

动态绑定是多态性的关键,那么编译器是如何做到动态绑定的呢。

在C++中,多态性主要通过虚函数来实现。        

什么是虚函数表?

虚函数表是一种数据结构,它存储了对象的虚函数的地址。每个包含虚函数的类都有一个对应的虚函数表。当创建一个对象时,编译器会在对象的内存布局中添加一个指向虚函数表的指针(通常称为虚函数指针或 vptr)。这个指针指向类的虚函数表。

虚函数表的工作原理

虚函数表的工作原理如下:

  1. 编译阶段:在编译阶段,对于定义了虚函数的类,编译器会在该类的类型信息中生成一个虚函数表。这个虚函数表是一个数组,其中包含了该类所有虚函数的地址。同时,编译器会在对象的内存布局中添加一个指向虚函数表的指针。

  2. 运行阶段:当调用一个虚函数时,实际上是通过对象的虚函数指针找到了对应的虚函数表,并在表中查找相应函数的地址,然后调用该函数。由于虚函数表是按照类层次结构组织的,因此在派生类的虚函数表中,会包含基类的虚函数表中的所有虚函数,并在需要时进行覆盖(重写)。

让我们通过一个简单的示例来说明虚函数表的概念:

#include <iostream>class Animal {
public:virtual void speak() {std::cout << "Animal speaks" << std::endl;}
};class Dog : public Animal {
public:void speak() override {std::cout << "Dog barks" << std::endl;}
};int main() {Animal* animal = new Dog();animal->speak(); // 运行时多态性delete animal;return 0;
}

在这个示例中,Animal 类包含一个虚函数 speak()Dog 类继承自 Animal 并重写了 speak() 函数。在 main() 函数中,我们创建了一个 Dog 对象的指针,并将其赋值给一个 Animal 类型的指针。当调用 animal->speak() 时,由于 speak() 是虚函数,实际上会通过对象的虚函数指针找到 Dog 类的虚函数表,并调用 Dog 类中的 speak() 函数,输出 "Dog barks"。

多态的优势和应用

多态性提供了更加灵活和可扩展的代码结构,具有以下优势:

  • 简化代码:通过多态性,我们可以将相同操作应用于不同的对象,从而减少代码重复。
  • 提高可维护性:使用多态性可以使代码更加模块化和可扩展,易于维护和更新。
  • 增强扩展性:通过继承和动态绑定,我们可以轻松地添加新的子类或扩展现有的功能,而不必修改现有的代码。

结语

多态性是面向对象编程的核心概念之一,它通过继承和动态绑定实现了代码的灵活性和可扩展性。理解多态性的原理和实现方式对于编写高质量的面向对象程序至关重要。通过充分利用多态性,我们可以编写出更加简洁、灵活和可维护的代码。

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

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

相关文章

大数据--hdfs--java编程

环境&#xff1a; virtualbox ubantu1604 Linux idea社区版2023 jdk1.8 hadoop相关依赖 使用java操作 1. 判断/user/stu/input/test.txt文件是否存在&#xff0c;存在则读出文件内容&#xff0c;打印在控制台上。反之&#xff0c;输出“文件不存在”。 package abc;impo…

二进制文件和为文本文件

二进制文件和为文本文件 根据数据的组织形式&#xff0c;数据文件被称为文本文件或者二进制文件。 数据在内存中以⼆进制的形式存储&#xff0c;如果不加转换的输出到外存的文件中&#xff0c;就是二进制文件。 如果要求在外存上以ASCII码的形式存储&#xff0c;则需要在存储前…

零成本使用Grass赚钱,简化教程,一学就会

文章目录 第一步&#xff1a;注册账户第二步&#xff1a;安装Grass Chrome插件1、离线安装&#xff08;推荐&#xff09;2、在线安装&#xff08;有外力的话推荐&#xff09; 第三步&#xff1a;登录Grass插件第四步&#xff1a;Grass开始运行结语 第一步&#xff1a;注册账户 …

计算机二级大题

题目来源&#xff1a;计算机二级Python半个月抱佛脚大法&#xff08;内呈上真题版&#xff09; - 知乎 1.大题1 注意csv文件读取的处理 ls[] for line in f: ls.append(line.strip(\n).split(,)) 2. 大题2 第一问&#xff1a; #计算有效票张数 fopen("vote.txt",…

wordpress给指定ID分类添加特定的字段

要在WordPress中为不同的分类添加特定的字段&#xff0c;您可以使用自定义字段&#xff08;Custom Fields&#xff09;功能。以下是一种方法&#xff0c;通过编写自定义的函数来实现。 首先&#xff0c;您需要创建一个自定义的函数来添加特定的字段。您可以在WordPress主题的f…

数据挖掘与机器学习 1. 绪论

于高山之巅&#xff0c;方见大河奔涌&#xff1b;于群峰之上&#xff0c;便觉长风浩荡 —— 24.3.22 一、数据挖掘和机器学习的定义 1.数据挖掘的狭义定义 背景&#xff1a;大数据时代——知识贫乏 数据挖掘的狭义定义&#xff1a; 数据挖掘就是从大量的、不完全的、有噪声的、…

【群晖】Docker Compose部署 Emby Server

【群晖】Docker Compose部署 Emby Server 本来群晖上面的 Emby 是用套件安装的&#xff0c;但是不巧的是前两天脑袋一抽装了两个插件&#xff0c;导致 Emby Server被当肉鸡了&#xff0c;还找不到脚本代码在哪儿&#xff0c;一天时间上传了3T的流量。无奈之下&#xff0c;只能尝…

【python绘图colorbar对齐】

[Toc]# 1、问题描述 python在绘图过程中&#xff0c;可能会出现colorbar高度与主图不匹配情况&#xff0c;需要进行调整&#xff0c;使得与主图高度对齐&#xff0c;使图像更美观。示例&#xff1a;colorbar位置高于主图 2、解决方法 通过调整shrink参数匹配对齐,pad调整x轴…

数据库范式--一起学习吧之数据库

一、数据库范式分类 数据库范式是关系数据库中的关系必须满足的规范化要求&#xff0c;主要用于减少数据冗余、提高数据的一致性和完整性。目前数据库范式主要有六种&#xff0c;从低到高依次是&#xff1a;第一范式&#xff08;1NF&#xff09;、第二范式&#xff08;2NF&…

《妈妈是什么》笔记(二) 让孩子自己做选择

经典摘录 孩子也会需要独立的空间做事情&#xff0c;求独立、求空间、求私隐 对于不管因为什么&#xff0c;别人在受到肯定和赞赏的时候&#xff0c;会对我们自己的心理带来因“比较”而产生的不适感甚至嫉妒感&#xff0c;进而在行为上影响了我们自己的节奏&#xff0c;产生一…

如何系统地自学Python

如何系统地自学Python 大家好&#xff01;今天&#xff0c;我要和大家聊聊一个老生常谈但又永不过时的话题——如何系统地自学Python。Python&#xff0c;这个既简单又强大的编程语言&#xff0c;已经成为许多初学者入门编程的首选。但问题来了&#xff0c;面对海量的学习资源…

【智能计算系统】神经网络基础代码实现

参考课程&#xff1a;智能计算系统 神经网络中常见的组成部分有&#xff1a;全连接层&#xff0c;激活函数&#xff0c;Softmax层。 全连接层 全连接层输入为一维向量&#xff08;维度为m&#xff09;&#xff0c;输出为一维向量&#xff08;维度为n&#xff09;。前向传播的…

ThingsBoard初始化数据库Postgres+Cassandra

本章将介绍ThingsBoard初始化数据PostgresCassandra&#xff0c;两种数据库结合使用&#xff0c;以及源码的编译安装。本机环境&#xff1a;Centos7、Docker、Postgres、Cassandra 环境安装 开发环境要求&#xff1a; docker &#xff1b;Docker&#xff1b;Postgres:Cassandr…

Qwen及Qwen-audio大模型微调项目汇总

Qwen及Qwen-audio可微调项目调研 可用来微调方法/项目汇总ps.大语言模型基础资料 可用来微调方法/项目汇总 Qwen github 项目自带的finetune脚本 可以参考https://blog.csdn.net/qq_45156060/article/details/135153920PAI-DSW中微调千问大模型&#xff08;阿里云的一个产品&a…

maven archetype 和普通的maven有啥区别

Maven是一个项目管理和构建自动化工具&#xff0c;主要用于Java项目&#xff0c;它基于项目对象模型&#xff08;POM&#xff09;。Maven可以通过其POM文件管理项目的构建、报告和文档。 而Maven Archetype是Maven的一个插件&#xff0c;主要用于为用户创建基于某个模版的新项…

Django日志(一)

一、概念与配置 1.1、概述 日志是程序员经常在代码中使用快速和方便的调试工具。它在调试方面比print更加的优雅和灵活 而且日志记录对于调试很有用,可以提供更多,更好的结构化,有关应用程序的状态和运行状况的信息 Django框架的日志通过python内置的logging模块实现的,可…

TCP TLS

TCP&#xff08;传输控制协议&#xff09;是一种面向连接的协议&#xff0c;用于在网络上可靠地传输数据。它提供了数据分段、重传、流量控制和拥塞控制等功能&#xff0c;以确保数据的可靠传输。TCP在传输层上工作&#xff0c;它使用IP&#xff08;Internet协议&#xff09;作…

LeetCode2671. Frequency Tracker

文章目录 一、题目二、题解 一、题目 Design a data structure that keeps track of the values in it and answers some queries regarding their frequencies. Implement the FrequencyTracker class. FrequencyTracker(): Initializes the FrequencyTracker object with …

前端视角如何理解“时间复杂度O(n)”

定义 时间复杂度是O(n) 意味着算法的执行时间与输入数据的大小成正比。 这里的n表示输入数据的数量。 假设有一个数组&#xff0c;需要遍历这个数组并打印出每个元素的值。 这个操作的时间复杂度就是O(n)&#xff0c;因为你需要执行n次操作&#xff0c;其中n是数组的长度。 …

力扣由浅至深 每日一题.11 加一

少年气&#xff0c;是历经千帆举重若轻地沉淀&#xff0c;也是乐观淡然笑对生活的豁达 —— 24.3.22 加一 给定一个由 整数 组成的 非空 数组所表示的非负整数&#xff0c;在该数的基础上加一。 最高位数字存放在数组的首位&#xff0c; 数组中每个元素只存储单个数字。 你可以…