c++多态机制

多态

在 C++ 中,多态(Polymorphism)是一种面向对象编程的重要概念,它允许不同类的对象对同一消息做出不同的响应。具体来说,多态性允许基类的指针或引用在运行时指向派生类的对象,并且根据对象的实际类型来调用相应的成员函数。
多态性是通过虚函数来实现的。当一个基类的成员函数被声明为虚函数时,派生类可以通过覆盖(重写)这个函数来提供自己的实现。在运行时,调用这个虚函数的时候,实际上调用的是指向对象的实际类型的版本。
C++ 中的多态性有两种形式:静态多态(编译时多态)和动态多态(运行时多态)。
1.静态多态(编译时多态): 主要是通过函数重载和模板实现的,例如,同一个函数名可以有多个版本,根据参数的类型和数量来决定调用哪个版本的函数。这种多态性在编译时就已经确定了。
2.动态多态(运行时多态): 主要是通过虚函数和继承实现的,例如,基类指针指向派生类对象,并调用虚函数。在运行时,根据对象的实际类型来决定调用哪个版本的函数。这种多态性在运行时才会确定。

静态多态

静态多态(也称为编译时多态或早期多态)是指在编译时就确定函数调用的方式,主要通过函数重载和模板来实现。在静态多态中,编译器在编译时根据函数的签名(函数名称和参数列表)来确定调用哪个函数版本。
静态多态主要有两种形式:
1.函数重载: 函数重载允许在同一作用域内声明多个函数,它们具有相同的名称但参数列表不同。在调用函数时,编译器根据传递的参数的数量、类型和顺序来选择匹配的函数。

#include <iostream>

// 函数重载示例
void print(int x) {
    std::cout << "Integer: " << x << std::endl;
}

void print(double x) {
    std::cout << "Double: " << x << std::endl;
}

int main() {
    print(5);       // 调用第一个 print 函数
    print(3.14);    // 调用第二个 print 函数
    return 0;
}

2.模板: 模板是一种通用编程技术,允许编写与特定类型无关的代码。通过使用模板,可以在不同类型的参数上执行相同的操作,而无需为每种类型编写不同的函数。

#include <iostream>

// 模板示例
template <typename T>
void print(T x) {
    std::cout << "Value: " << x << std::endl;
}

int main() {
    print(5);           // 实例化一个 int 类型的 print 函数
    print(3.14);        // 实例化一个 double 类型的 print 函数
    print("Hello");     // 实例化一个 const char* 类型的 print 函数
    return 0;
}

在这里插入图片描述

在静态多态中,函数调用的决定在编译时完成,因此性能更高。然而,静态多态的缺点是在编写代码时必须明确指定每个函数的具体版本,如果有大量的重载或模板,可能会导致代码量增加和可读性降低。

动态多态

动态多态(也称为运行时多态或晚期多态)是指在程序运行时根据对象的实际类型来决定调用哪个函数版本。动态多态性通过虚函数和继承来实现,在编译时无法确定函数调用的具体版本,而是在运行时根据对象的类型动态确定。
动态多态的实现需要满足以下两个条件:
1.基类中声明虚函数:在基类中将函数声明为虚函数,这样编译器就会在运行时进行函数调用的动态绑定。
2.派生类重写虚函数:派生类中可以通过重写(覆盖)基类中的虚函数来提供自己的实现。在调用这个虚函数时,会根据对象的实际类型来决定调用哪个版本的函数。
下面是一个简单的示例,演示了动态多态的用法:

#include <iostream>

// 基类
class Animal {
public:
    // 虚函数
    virtual void makeSound() {
        std::cout << "Animal makes a sound" << std::endl;
    }
};

// 派生类
class Dog : public Animal {
public:
    // 重写基类的虚函数
    void makeSound() override {
        std::cout << "Dog dog" << std::endl;
    }
};

// 派生类
class Cat : public Animal {
public:
    // 重写基类的虚函数
    void makeSound() override {
        std::cout << "Cat cat" << std::endl;
    }
};

int main() {
    // 创建派生类对象
    Dog dog;
    Cat cat;

    // 基类指针指向派生类对象
    Animal* ptr1 = &dog;
    Animal* ptr2 = &cat;

    // 通过基类指针调用虚函数,实现多态
    ptr1->makeSound(); // 调用的是派生类 Dog 的 makeSound() 函数
    ptr2->makeSound(); // 调用的是派生类 Cat 的 makeSound() 函数

    return 0;
}

Animal 类有一个虚函数 makeSound(),而 Dog 和 Cat 类分别继承自 Animal 类并重写了 makeSound() 函数。在 main() 函数中,我们创建了 Dog 和 Cat 类的对象,并将基类指针指向这些对象,然后通过基类指针调用虚函数 makeSound()。由于 makeSound() 是虚函数,所以在运行时根据对象的实际类型来决定调用哪个版本的函数,从而实现了动态多态性。

父类指针指向子类对象

在 C++ 中,可以使用父类的指针来指向子类的对象,这是实现多态的一种常见方式。这种行为被称为向上转型(upcasting),它允许您通过基类的接口来操作派生类的对象。这在面向对象编程中是非常有用的,因为它使代码更加灵活和可扩展。
下面是一个简单的示例说明了如何使用父类的指针来指向子类的对象:

#include <iostream>

// 基类
class Base {
public:
    virtual void display() {
        std::cout << "Base class display() called" << std::endl;
    }
};

// 派生类
class Derived : public Base {
public:
    void display() override {
        std::cout << "Derived class display() called" << std::endl;
    }
};

int main() {
    // 创建派生类对象
    Derived derivedObj;

    // 使用基类指针指向派生类对象
    Base* basePtr = &derivedObj;

    // 通过基类指针调用虚函数,实现多态
    basePtr->display(); // 调用的是派生类的 display() 函数

    return 0;
}

Base 是基类,Derived 是派生类。Base 类有一个虚函数 display(),Derived 类重写了 display() 函数。在 main() 函数中,我们创建了 Derived 类的对象 derivedObj,然后使用 Base 类的指针 basePtr 指向了 derivedObj。最后,通过 basePtr 调用 display() 函数,由于 display() 函数是虚函数,所以调用的是 Derived 类中的版本,实现了多态行为。

方法调用

在 C++ 中,如果父类通过指针或引用调用一个虚函数,而这个虚函数在子类中被重写(override),那么调用的实际方法将取决于指针或引用所指向的对象的类型。这就是多态的体现。
具体来说,如果父类指针或引用指向的是子类对象,那么调用的方法将是子类中重写的版本;如果指针或引用指向的是父类对象,那么调用的方法将是父类中的版本。
下面是一个示例来说明这一点:

#include <iostream>

// 基类
class Base {
public:
    virtual void show() {
        std::cout << "Base class show()" << std::endl;
    }
};

// 派生类
class Derived : public Base {
public:
    void show() override {
        std::cout << "Derived class show()" << std::endl;
    }
};

int main() {
    // 创建派生类对象
    Derived derivedObj;

    // 使用基类指针指向派生类对象
    Base* basePtr = &derivedObj;

    // 通过基类指针调用虚函数,实现多态
    basePtr->show(); // 调用的是派生类的 show() 函数

    return 0;
}

Base 类是基类,Derived 类是派生类。在 main() 函数中,我们创建了 Derived 类的对象 derivedObj,然后使用 Base 类的指针 basePtr 指向了 derivedObj。最后,通过 basePtr->show() 调用 show() 函数,由于 show() 是虚函数,因此调用的是 Derived 类中的版本,而不是 Base 类中的版本。

2024年5月11日21:04:05
疏影斜横水清浅,暗香浮动月黄昏。

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

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

相关文章

日报表定时任务优化历程

报表需求背景 报表是一个很常见的需求&#xff0c;在项目中后期往往会需要加多种维度的一些统计信息&#xff0c;今天就来谈谈上线近10个月后的一次报表优化优化之路&#xff08;从一天报表跑需要五分钟&#xff0c;优化至秒级&#xff09; 需求&#xff1a;对代理商进行日统计…

BUUCTF[PWN]

BUUCTF[PWN] 题目&#xff1a;warmup_csaw_2016 地址&#xff1a;warmup_csaw_2016ida打开&#xff0c;进main函数&#xff1a;gets函数的栈溢出&#xff1a;给出了sub_40060D函数的地址直接&#xff0c;溢出到sub_40060D的地址即可&#xff1a; from pwn import *p remote…

vue 孙组件调用父组件的方法

通过组件内的 传递方法名称&#xff0c;可以实现孙组件调用父组件。 代码如下&#xff1a; index.html <!DOCTYPE html> <html> <head><meta charset"utf-8"><script src"/framework/vue-2.7.16.min.js"></script>…

数字孪生引擎国产信创环境适配靠谱么?

近期我们组织了一次国产化环境适配以及产品国产化产品替换的交流&#xff0c;虽然从属于不同的业务条线&#xff0c;但是在过去一段时间多多少少都承受不同程度的信创压力&#xff0c;尤其是自然资源业务方面&#xff0c;由于自然资源大多数的业务是属于强GIS的范畴&#xff0c…

基于单片机的直流电机检测与控制系统

摘要&#xff1a; 文章设计一款流电机控制系统&#xff0c;以 STC89C51 作为直流电机控制系统的主控制器&#xff0c;采用 LM293 做为驱动器实现 对直流电机的驱动&#xff0c;采用霍尔实现对直流电机速度的检测&#xff1b;本文对直流电机控制系统功能分析&#xff0c;选择确…

Colab/PyTorch - 003 Transfer Learning For Image Classification

Colab/PyTorch - 003 Transfer Learning For Image Classification 1. 源由2. 迁移学习(ResNet50)2.1 数据集准备2.2 数据增强2.3 数据加载2.4 迁移学习2.5 数据集训练&验证2.6 模型推理 3. 总结4. 参考资料 1. 源由 迁移学习已经彻底改变了 PyTorch 中处理图像分类的方式…

搜歌网搜索各种类型音乐,统统歌曲转换格式mp3,轻松实现音乐自由!

在互联网的广阔天地中&#xff0c;音乐爱好者们总能找到满足自己需求的平台。其中&#xff0c;支持全网搜歌的网站无疑是一个值得推荐的音乐探索乐园。无论是寻找经典老歌&#xff0c;还是发掘新兴音乐&#xff0c;搜他们都能为音乐爱好者提供一站式的服务。 一般支持全网搜索…

微信投票源码系统至尊版 吸粉变现功能二合一

源码简介 微信投票系统在营销和社交互动中发挥着多方面的作用&#xff0c;它能够提升用户的参与度和品牌曝光度&#xff0c;还是一种有效的数据收集、营销推广和民主决策工具。 分享一款微信投票源码系统至尊版&#xff0c;集吸粉变现功能二合一&#xff0c;全网独家支持礼物…

py黑帽子学习笔记_网络编程工具

tcp客户端 socket.AF_INET表示使用标准IPV4地址和主机名 SOCK_STREAM表示这是一个TCP客户端 udp客户端 udp无需连接&#xff0c;因此不需要client.connect这种代码 socket.SOCK_DGRAM是udp的 tcp服务端 server.listen(5)表示设置最大连接数为5 发现kill server后端口仍占用…

【论文阅读笔记】jTrans(ISSTA 22)

个人博客地址 [ISSTA 22] jTrans&#xff08;个人阅读笔记&#xff09; 论文&#xff1a;《jTrans: Jump-Aware Transformer for Binary Code Similarity》 仓库&#xff1a;https://github.com/vul337/jTrans 提出的问题 二进制代码相似性检测&#xff08;BCSD&#xff0…

Stable Diffusion的技术原理

一、Stable Diffusion的技术原理 Stable Diffusion是一种基于Latent Diffusion Models&#xff08;LDMs&#xff09;实现的文本到图像&#xff08;text-to-image&#xff09;生成模型。其工作原理主要基于扩散过程&#xff0c;通过模拟数据的随机演化行为&#xff0c;实现数据…

壹资源知识付费系统源码-小程序端+pc端

最新整理优化&#xff0c;含微信小程序和pc网页。内置几款主题&#xff0c;并且可以自己更改主题样式&#xff0c;各区块颜色&#xff0c;文字按钮等。 适用于知识付费类资源类行业。如&#xff1a;项目类&#xff0c;小吃技术类&#xff0c;图书类&#xff0c;考研资料类&…

修改表空间对应数据文件的大小

Oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 表空间与数据文件紧密相连&#xff0c;相互依存&#xff0c;创建表空间的时候需设置数据文件大小。 在后期实际应用中&#xff0c;如果实际存储的数据量超出事先设置的数据…

本地运行.net项目

有时候需要我们自己做一个.net的课设项目&#xff0c;但是我们有了代码后却不知道怎么运行。我们0基础来学习一下如何运行一个.net项目 1.安装visual studio 2022 不用安装老版本&#xff0c;新版就可以。安装好了2022版本&#xff0c;这是一个支持web的IDE&#xff0c;我们可…

Java----数组的定义和使用

1.数组的定义 在Java中&#xff0c;数组是一种相同数据类型的集合。数组在内存中是一段连续的空间。 2.数组的创建和初始化 2.1数组的创建 在Java中&#xff0c;数组创建的形式与C语言又所不同。 Java中数组创建的形式 T[] 数组名 new T[N]; 1.T表示数组存放的数据类型…

ARM单片机实现流水灯(GD32)

根据上图可知使用的引脚分别是PA8,PE6,PF6流水灯功能的实现要分别初始化这几个引脚 流水灯实现 编写流水灯代码 LED.C #include "gd32f30x.h" // Device header #include "Delay.h" // 初始化LED灯 void LED_Init(void){// 使能RCU时钟…

词令蚂蚁庄园今日答案如何在微信小程序查看蚂蚁庄园今天问题的正确答案?

词令蚂蚁庄园今日答案如何在微信小程序查看蚂蚁庄园今天问题的正确答案&#xff1f; 1、打开微信&#xff0c;点击搜索框&#xff1b; 2、打开搜索页面&#xff0c;选择小程序搜索&#xff1b; 3、在搜索框&#xff0c;输入词令搜索点击进入词令微信小程序&#xff1b; 4、打开…

1290.二进制链表转整数

给你一个单链表的引用结点 head。链表中每个结点的值不是 0 就是 1。已知此链表是一个整数数字的二进制表示形式。 请你返回该链表所表示数字的 十进制值 。 示例 1&#xff1a; 输入&#xff1a;head [1,0,1] 输出&#xff1a;5 解释&#xff1a;二进制数 (101) 转化为十进制…

三大消息传递机制区别与联系

目录 总结放开头 1、定义区别&#xff1a; EventBus Broadcast Receiver Notification 2、使用区别: EventBus Broadcast Receiver Notification 3、补充通知渠道&#xff1a; 通知渠道重要程度 总结放开头 BroadCast Receiver:属于安卓全局监听机制&#xff0c;接收…

软件开发项目实施方案-精华资料(Word原件)

依据项目建设要求&#xff0c;对平台进行整体规划设计更新维护&#xff0c;对系统运行的安全性、可靠性、易用性以及稳健性进行全新设计&#xff0c;并将所有的应用系统进行部署实施和软件使用培训以及技术支持。 根据施工总进度规划&#xff0c;编制本项目施工进度计划表。依据…