C++: 多态

news2024/12/29 11:00:18

1.多态的概念

1.1概念

多态:  是面向对象编程 中的一个重要概念,它允许不同的对象以一种统一的方式进行操作。

具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态

多态性使得可以使用相同的接口来处理不同的数据类型,而无需关心具体的数据类型。

--静态多态

一般指的是函数重载, 通过函数名修饰规则, 在编译的时候进行相关匹配

--动态的多态

运行后去虚表当中找, 与指向的对象有关, 指向谁就调用谁

2.多态的定义及使用

2.1多态构成的条件

1.虚函数的重写 -- 三同(返回值, 函数名,参数)

        --例外(协变):返回值可以不同, 但必须是父子关系的指针或者引用

        --例外:子类的虚函数可以不+virtual

2.父类的指针或引用调用

2.2虚函数

虚函数:即被virtual修饰的类成员函数称为虚函数

class Person {
public:
    virtual void BuyTicket() { cout << "买票-全价" << endl;}
};

2.3虚函数的重写

虚函数的重写(覆盖):派生类中有一个跟基类完全相同的虚函数(即派生类虚函数与基类虚函数的返回值类型、函数名字、参数列表完全相同),称子类的虚函数重写了基类的虚函数。

class Person {
public:
    virtual void BuyTicket() { cout << "买票-全价" << endl; }
};
class Student : public Person {
public:
    virtual void BuyTicket() { cout << "买票-半价" << endl; }
    //在重写基类虚函数时,派生类的虚函数可以不加virtual关键字
    //因为派生类继承了基类的虚函数属性(但不建议这么用)
};

--例外

1.协变

派生类重写基类虚函数时,与基类虚函数返回值类型不同,但必须是父子关系的指针或者引用

class A{};
class B : public A {};

class Person {
public:
    virtual A* f() {return new A;}
};

class Student : public Person {
public:
    virtual B* f() {return new B;}
};

2.析构函数

因为编译器对派生类的析构函数进行了特殊处理,  全部都处理为destructor

--如果基类的析构函数为虚函数,此时派生类析构函数只要定义,无论是否加virtual关键字,
都与基类的析构函数构成重写

class Person {
public:
    virtual ~Person() {cout << "~Person()" << endl;}
};

class Student : public Person {
public:
    virtual ~Student() { cout << "~Student()" << endl; }
};

只有派生类Student的析构函数重写了Person的析构函数,下面的delete对象调用析构函
数,才能构成多态,才能保证p1和p2指向的对象正确的调用析构函数

Person* p1 = new Person;
Person* p2 = new Student;
delete p1;
delete p2;

2.4C++11中的override与final

1. final:修饰虚函数,表示该虚函数不能再被重写

class Car
{
public:
    virtual void Drive() final {}
};

class Benz :public Car
{
public:
    virtual void Drive() {cout << "Benz-舒适" << endl;}
};

2. override: 检查派生类虚函数是否重写了基类某个虚函数,如果没有重写编译报错

class Car{
public:
    virtual void Drive(){}
};

class Benz :public Car {
public:
    virtual void Drive() override {cout << "Benz-舒适" << endl;}
};

2.5重载, 重写(覆盖), 重定义(隐藏)的对比

3抽象类

3.1概念

在虚函数的后面写上 =0 ,则这个函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口类)

class Car
{
public:
    virtual void Drive() = 0;
};

3.2接口继承与实现继承

--普通函数的继承是一种实现继承,派生类继承了基类函数,可以使用函数,继承的是函数的实现。

--虚函数的继承是一种接口继承,派生类继承的是基类虚函数的接口,目的是为了重写,达成
多态,继承的是接口。

--所以如果不实现多态,不要把函数定义成虚函数。

3.3抽象类的作用

1.抽象类不能实例化出对象。派生类继承后也不能实例化出对象,只有重写纯虚函数,派生类才能实例化出对象。纯虚函数规范了派生类必须重写

2.纯虚函数更体现出了接口继承

4.原理

4.1虚函数表

虚函数表: 是一个指针数组, 存放指向虚函数的指针. 当一个类里有虚函数的时候,会有一个虚表指针, 用来指向这个虚表   

  

同一类的对象共用一个虚表

1.虚表是在什么阶段生成的? --编译的时候

2.对象中的虚表指针什么时候初始化的? --构造函数的初始化列表

3.虚表存在哪里? 常量区

4.2多态的原理

通过虚表完成:

        --如果不满足多态 看调用者的类型, 调用这个类型的成员函数

        --如果满足多态 看指向的对象的类型, 调用这个类型的成员函数

满足多态以后的函数调用,不是在编译时确定的,是运行起来以后到对象的中去找的。

不满足多态的函数调用时,   用编译时确认好的

4.3动态绑定与静态绑定

1. 静态绑定又称为前期绑定(早绑定),在程序编译期间确定了程序的行为,也称为静态多态,比如:函数重载

2. 动态绑定又称后期绑定(晚绑定),是在程序运行期间,根据具体拿到的类型确定程序的具体行为,调用具体的函数,也称为动态多态

5.总结

1. inline函数可以是虚函数吗?

--可以,不过编译器就忽略inline属性,这个函数就不再是inline,因为虚函数要放到虚表中去。


2. 静态成员可以是虚函数吗?

--不能,因为静态成员函数没有this指针,使用类型::成员函数的调用方式无法访问虚函数表,所以静态成员函数无法放进虚函数表。


3. 构造函数可以是虚函数吗?

--不能,因为对象中的虚函数表指针是在构造函数初始化列表阶段才初始化的。


4. 析构函数可以是虚函数吗?什么场景下析构函数是虚函数?

--可以,并且最好把基类的析构函数定义成虚函数。基类指针指向派生类对象


5. 对象访问普通函数快还是虚函数更快?

--如果是普通对象,是一样快的。如果是指针对象或者是引用对象,则调用的普通函数快,因为多态调用,运行时调用虚函数需要到虚函数表中去查找。

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

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

相关文章

【wxWidgets 实现Window窗口系统】

【wxWidgets 实现Window窗口系统】 简介效果 简介 wxWidgets 嗯 还不错,速度快,文档资源全面,轻巧,免费等等,好处一堆但是,窗口透明效果不咋地,不知道是我显卡问题还是啥设置透明全成黑色了,想折腾成JavaFx那样的界面,瞬间没感觉了,不管怎么折腾都达不到预期效果,但是可以实现…

数据库数据恢复-oracle数据库报错:数据库无法打开的数据恢复案例

oracle数据库数据恢复环境&#xff1a; 一台服务器&#xff0c;底层由12块硬盘组成一组磁盘阵列&#xff0c;上层操作系统上运行oracle数据库。 oracle数据库故障&#xff1a; 数据库无法打开&#xff0c;报错&#xff1a;“数据库无法打开”&#xff0c;管理员第一时间将服务器…

英国音乐技术公司【Audoo】完成500万美元融资

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 猛兽财经获悉&#xff0c;总部位于英国伦敦的音乐技术公司【Audoo】今日宣布已完成500万美元融资。 本轮融资完成后Audoo的总融资金额已达到2200万美元&#xff0c;本轮融资的投资者包括&#xff1a;Elton John&#xff0c…

【计算机毕设选题推荐】物流管理系统SpringBoot+Vue

前言&#xff1a;我是IT源码社&#xff0c;从事计算机开发行业数年&#xff0c;专注Java领域&#xff0c;专业提供程序设计开发、源码分享、技术指导讲解、定制和毕业设计服务 项目名 基于SpringBoot的物流管理系统 技术栈 SpringBootVueMySQLMaven 文章目录 一、物流管理系统…

电压放大器在超声领域中有哪些应用场景

电压放大器在超声领域中有多种应用场景。超声技术已经成为医学、工业检测和无损检测等领域中常用的非侵入性检测工具。电压放大器在超声设备中扮演着关键的角色&#xff0c;下面安泰电子将详细介绍电压放大器在超声领域中的应用场景。 超声发生器 超声发生器是产生高频声波的设…

相关性网络图

教程链接&#xff1a; 相关性网络图 往期文章&#xff1a; 1. 复现SCI文章系列专栏 2. 《生信知识库订阅须知》,同步更新&#xff0c;易于搜索与管理。 3. 最全WGCNA教程&#xff08;替换数据即可出全部结果与图形&#xff09; WGCNA分析 | 全流程分析代码 | 代码一 WGCNA分…

深入解剖线程池(ThreadPoolExecutor)

目录 1 线程池&#xff08;ThreadPoolExecutor&#xff09;2 线程池的使用&#xff08;Executors&#xff09;2.1 newFixedThreadPool2.2 newCachedThreadPool2.3 newSingleThreadExecutor2.4 newScheduledThreadPool 多线程应用程序中&#xff0c;线程的创建和销毁开销相对较高…

新手选MT4老手选MT5,有道理吗?anzo capital昂首资本这样分析

最近anzo capital昂首资本一直在分享MT4和MT5的常识&#xff0c;发现真的评论区惊现大神&#xff0c;竟直接作出总结&#xff1a;新手选MT4老手选MT5。不管正确与否&#xff0c;但是这些真的很炸裂啊&#xff01; 首先在指标和分析对象上&#xff0c;MT4有30个内置指标和33个分…

霸榜SPC-1,成立才3年多,这家中国的存储初创公司凭什么?

史书云&#xff1a;分久必合&#xff0c;合久必分。 高端存储“软硬件解耦”大势所趋。 【全球存储观察 &#xff5c; 热点关注】 提及SPC-1&#xff0c;在存储行业&#xff0c;可谓无人不知&#xff0c;无人不晓。 然而&#xff0c;对于一家成立于2020年1月19日&#xff0c…

2023年09月 C/C++(一级)真题解析#中国电子学会#全国青少年软件编程等级考试

C/C编程&#xff08;1~8级&#xff09;全部真题・点这里 Python编程&#xff08;1~6级&#xff09;全部真题・点这里 第1题&#xff1a;日期输出 给定两个整数&#xff0c;表示一个日期的月和日。请按照"MM-DD"的格式输出日期&#xff0c;即如果月和日不到2位时&…

Arduino是如何实现打开串口时,程序复位的?

引言 使用过Arduino的都应该发现过&#xff0c;在打开Arduino IDE自带的COM串口助手的时候&#xff0c;Arduino开发板会复位。在打开其他串口助手的时候也会。这是为什么呢&#xff1f; 原因分析 首先看看arduino的原理图&#xff1a; 我们可以看看与复位引脚相关的部…

【EI会议征稿】第四届材料化学与复合材料国际学术会议(MCCM 2023)

第四届材料化学与复合材料国际学术会议&#xff08;MCCM 2023&#xff09; 2023 4th International Conference on Material Chemistry and Composite Materials (MCCM 2023) 第四届材料化学与复合材料国际学术会议&#xff08;MCCM 2023&#xff09;将于2023年12月22-24日…

shiro550复现环境搭建

前言 Shiro反序列化漏洞指的是Apache Shiro安全框架中的一个潜在漏洞&#xff0c;该漏洞可能导致攻击者能够通过精心构造的恶意序列化对象来执行任意代码或进行拒绝服务&#xff08;DoS&#xff09;攻击。 这种漏洞的根源是在Shiro的RememberMe功能中&#xff0c;当用户选择“…

一个简单算法解决集群定时任务重复执行

好久不见&#xff0c;今天给大家分享一个非常好用的方法&#xff0c;来解决集群定时任务如何避免重复执行的问题。 需求描述&#xff1a; 大家都知道&#xff0c;定时任务在我们实际项目当中是会经常被使用到的&#xff0c;在生产环境中&#xff0c;为了保证服务的高可用&…

做一个物联网的后台程序与数据库设计

数据库部分 先设计一个简单的数据库。表结构如下: sql语句如下: SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0;-- ---------------------------- -- Table structure for realtimedata -- ---------------------------- DROP TABLE IF EXISTS `realtimedata`

【pycharm】sqlite3:Driver class ‘org.sqlite.JDBC‘ not found

pycharm 连接sqlite3的时候&#xff0c;点击&#xff1a;Test Connection 提示&#xff1a;Driver class ‘org.sqlite.JDBC’ not found. 点击&#xff1a;Download missing driver files 点击&#xff1a;Test Connection 这样就ok了&#xff1b;

执行make menuconfig问题的解决

执行make menuconfig 出现问题 在终端输入以下命令执行。 make menuconfig在终端输入上面命令执行时&#xff0c;没有成功运行&#xff0c;出现了如下的问题。 出现这个错误提示意味着在运行 make menuconfig 命令时&#xff0c;系统找不到 ncurses 库。ncurses 是一种文本用…

Python系列:彩色日志详解

前言 在使用Python进行编程时&#xff0c;我相信很多小伙伴都有一个共通的习惯&#xff0c;就是不管在什么场景下&#xff0c;都会先使用print()将我们获取到的数据打印出来以此来确保自己的代码没有问题。虽说在pycharm中提供了DEBUG功能&#xff0c;但是还是有很多小伙伴用不…

你知道期权和期货有什么关联和区别吗?解析一下!

随着金融市场的不断发展&#xff0c;期权和期货成为了两种常见的金融衍生品&#xff0c;它们都具有规避风险和发现价格的功能。很多入门不知道期权和期货哪个更好&#xff0c;下文科普你知道期权和期货有什么关联和区别吗&#xff1f;解析一下&#xff01;本文来源&#xff1a;…

AI Web3 盛会「EDGE」在港闭幕,融云国际影响力持续提升

&#x1f446;点击报名「爱嗨游」线上发布会 9 月 25 日至 27 日&#xff0c;全球规模最大的 AI & Web3 投资盛会——EDGE 峰会在中国香港举办&#xff0c;融云作为战略合作伙伴与来自世界各地的企业家、投资人、学者和热门项目方一同完成了这一盛会。关注【融云全球互联网…