7.C++:多态

news2024/12/24 2:32:24

一、 virtual关键字

//1.可以修饰原函数,为了完成虚函数的重写,满足多态的条件之一;

//2.可以在菱形继承中,完成虚继承,解决数据冗余和二义性;

两个地方使用同一关键字,但二者间没有一点关联

二、多态的构成条件

继承中要构成多态还有两个条件
1. 必须通过基类的指针或者引用调用虚函数
2. 被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写
重写:派生类中有一个跟基类完全相同的虚函数(返回值类型,函数名字,参数列表完全相同)

//1.满足多态的条件:跟对象有关,指向哪个对象就调用它的虚函数

//2.不满足多态条件:跟类型有关,调用的类型是谁,就去调用它的。 

class Person 
{
public:
    virtual void BuyTicket() { cout << "买票-全价" << endl; }
};
class Student : public Person
{
public:
    virtual void BuyTicket() { cout << "买票-半价" << endl; }
};
void Func(Person& p)   //只能用父类,与切片有关
{
    p.BuyTicket();
}
int main()
{
    Person ps;
    Student st;
    Func(ps);   //调用的父类的
    Func(st);   //调用的子类的
    return 0;
}
//或者
void Func(Person* p) 
{
    p->BuyTicket();
}
int main()
{
    Person ps;
    Student st;
    Func(&ps);   //调用的父类的
    Func(&st);   //调用的子类的
    return 0;
}

三、虚函数重写的两个例外

3.1 协变(基类与派生类虚函数返回值类型不同)

//1.基类虚函数返回基类对象的指针或者引用,派生类虚函数返回派生类对象的指针或者引用

//2.父类函数返回的类型可以是其他的父类指针,子类同理

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; } //返回类型不同,仍构成重写
};

3.2析构函数的重写(基类与派生类析构函数的名字不同)

如果基类的析构函数为虚函数,此时派生类析构函数只要定义,无论是否加virtual关键字,都与基类的析构函数构成重写,虽然基类与派生类析构函数名字不同。虽然函数名不相同,看起来违背了重写的规则,其实不然,这里可以理解为编译器对析构函数的名称做了特殊处理,编译后析构函数的名称统一处理成destructor。
class Person 
{
public:
    virtual ~Person() { cout << "~Person()" << endl; }
};

class Student : public Person 
{
public:
    virtual ~Student() { cout << "~Student()" << endl; }
};
// 只有派生类Student的析构函数重写了Person的析构函数,下面的delete对象调用析构函数,才能构成
//多态,才能保证p1和p2指向的对象正确的调用析构函数。
int main()
{
    Person* p1 = new Person;
    Person* p2 = new Student;
    delete p1;
    delete p2;
    return 0;
}

输出:

~Person()
~Student()
~Person()  //调用子类析构后,会自动调用父类的析构


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

class Student : public Person {
public:
     ~Student() { cout << "~Student()" << endl; }
};
//不构成多态
int main()
{
    Person* p1 = new Person;
    Person* p2 = new Student;
    delete p1;
    delete p2;
    return 0;
}

输出:

~Person()
~Person() 


 四、override和final

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

class Car
{
public:
    virtual void Drive() final {}  //此类不能被重写
};
class Benz :public Car
{
public:
    virtual void Drive() { cout << "Benz-舒适" << endl; }
};
class Car final
{
public:
    virtual void Drive()  {}  
};
class Benz :public Car //不能继承被final修饰的父类
{
public:
    virtual void Drive() { cout << "Benz-舒适" << endl; }
};

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

class Car
{
public:
 virtual void Drive(){}
};
class Benz :public Car 
{
public:  //检查是否重写
 virtual void Drive() override {cout << "Benz-舒适" << endl;}
};

五、重载、覆盖(重写)、隐藏(重定义)的对比


六、 抽象类

6.1 概念

//1.在虚函数的后面写上 =0 ,则这个函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口类),抽象类不能实例化出对象
//2.派生类继承后也不能实例化出对象,只有重写纯虚函数,派生类才能实例化出对象
class Car
{
public:
    virtual void Drive() = 0;
};
class Benz :public Car
{
public:
};
int main()
{
    //Car cc; 不可实例化对象
    //Benz bb; 仍是一个抽象类
    return 0;
}
class Car
{
public:
    virtual void Drive() = 0; //强制子类重写
};
class Benz :public Car
{
public:
    virtual void Drive()  //重写纯虚函数
    {
        cout << "Benz-舒适" << endl;
    }
};
int main()
{
    Benz bb; //可以创建
    return 0;
}

6.2 接口继承和实现继承

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

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

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


七、动态绑定与静态绑定

1. 静态绑定又称为前期绑定(早绑定),在程序编译期间确定了程序的行为也称为静态多 ,比如:函数重载
2. 动态绑定又称后期绑定(晚绑定),是在程序运行期间,根据具体拿到的类型确定程序的具体行为,调用具体的函数,也称为动态多态
int i = 0;
double d = 1.1;
//静态绑定,静态的多态(静态:编译时)
f1(i);
f1(d);
//动态绑定,动态的多态(动态:运行时)
Base* p = new Base;
p->Func1();
p = new Derive;
p->Func1();

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

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

相关文章

鸿蒙入门04-真机运行“遥遥领先”

如果你有一台真的 "遥遥领先"那么是可以直接在手机上真机运行你的项目的我们也来尝试一下运行 一、手机设置开发者模式 打开手机设置 打开手机设置界面 向下滑动到关于手机位置 快速连续点击版本号位置 下图所示位置快速连续点击 打开 3 - 5 次即可 会提示您已经进…

Jackson 2.x 系列【25】Spring Boot 集成之起步依赖、自动配置

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Jackson 版本 2.17.0 本系列Spring Boot 版本 3.2.4 源码地址&#xff1a;https://gitee.com/pearl-organization/study-jaskson-demo 文章目录 1. 前言2. 起步依赖3. 自动配置3.1 JacksonPrope…

负载均衡集群——HAProxy

目录 1 HAProxy介绍 2 功能简介 3 实验组网介绍 4 实验步骤 4.1 通过 HAProxy 实现简单负载均衡调度功能 步骤 1 安装 HAProxy 步骤 2 修改配置 HAProxy 文件 4.2 HAProxy 监控页面配置 步骤 1 修改 HAProxy 配置文件 步骤 2 查看监控页面 3.3 HAProxy 日志相关配置 …

超详细!Python中 pip 常用命令

相信对于大多数熟悉Python的人来说&#xff0c;一定都听说并且使用过pip这个工具&#xff0c;但是对它的了解可能还不一定是非常的透彻&#xff0c;今天小编就来为大家介绍10个使用pip的小技巧&#xff0c;相信对大家以后管理和使用Python当中的标准库会有帮助。 安装 当然在…

论文解读:FREE LUNCH FOR FEW-SHOT LEARNING: DISTRIBUTION CALIBRATION

文章汇总 问题 学习到的模型很容易因为只有少数训练样本形成的有偏分布而变得过拟合。 动机 我们假设特征表示中的每个维度都遵循高斯分布&#xff0c;因此分布的均值和方差可以借鉴类似类的均值和方差&#xff0c;这些类的统计量可以通过足够数量的样本得到更好的估计。 …

PHP反序列化命令执行+PHP反序列化POP大链 +PHP反序列化基础

[题目信息]&#xff1a; 题目名称题目难度PHP反序列化命令执行1 [题目考点]&#xff1a; 反序列化命令执行&#xff0c;获取题目flag。[Flag格式]: SangFor{t5euvZ_OB8Jd_h2-}[环境部署]&#xff1a; docker-compose.yml文件或者docker tar原始文件。 docker-compose up …

ArcGIS三维景观分层显示

今天将向大家介绍的事在ArcGIS中如何创建多层三维显示。 地表为影像的 地表为地形晕渲的 在土壤分层、油气分层等都有着十分重要的应用。下面我们具体来看看实现过程 一、 准备数据及提取栅格范围 我们这次准备的数据是之前GIS100例-30讲的案例数据。《ArcGIS三维影像图剖面图…

【网站项目】学习资料销售平台 小程序

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

用c++写一个代码解析器需要向哪方面学习?

我以前在中小游戏公司工作的时候&#xff0c;其中一项比较琐碎的工作就是为游戏项目建库建表&#xff0c;主要是为了做数据分析。作为一个职能部门的打杂PHP&#xff0c;对游戏业务并没有什么发言权&#xff0c;但是每次建库建表&#xff0c;却是苦不堪言。 同时部门的基础设施…

EPP和EDR是什么,如何提高端点安全性

端点保护平台&#xff08;EPP&#xff09;和端点检测和响应&#xff08;EDR&#xff09;工具是两种常用于保护端点系统免受威胁的安全产品。EPP 是一种全面的安全解决方案&#xff0c;提供一系列功能来检测和防止对端点设备的威胁。同时&#xff0c;EDR专门用于实时监控、检测和…

CC254X 8051芯片手册介绍

1 8051CPU 8051是一种8位元的单芯片微控制器&#xff0c;属于MCS-51单芯片的一种&#xff0c;由英特尔(Intel)公司于1981年制造。Intel公司将MCS51的核心技术授权给了很多其它公司&#xff0c;所以有很多公司在做以8051为核心的单片机&#xff0c;如Atmel、飞利浦、深联华等公…

AI讲师大模型培训老师叶梓:大模型应用的方向探讨

大模型应用的关键方向及其落地案例可以从多个角度进行探讨&#xff0c;结合最新的研究和实际应用案例&#xff0c;我们可以更全面地理解这些技术如何推动社会和经济的发展。 Agent&#xff08;数字代理&#xff09;: 方向说明:Agent方向的AI技术旨在创建能够独立执行任务、做出…

redis_watchDog机制

文章目录 介绍机制介绍任务开始任务释放 介绍 redis的watchDog机制实现了超时续约的功能&#xff0c;简单来说就是在获取锁成功以后&#xff0c;开启一个定时任务&#xff0c;这个任务每隔一段时间(relaseTime / 3)&#xff0c;重置超时时间&#xff0c;避免的因业务阻塞导致锁…

比特币L2项目主网密集上线:新业态背后的挑战与机遇

随着加密货币行业的快速发展&#xff0c;比特币Layer 2&#xff08;以下简称L2&#xff09;项目的主网密集上线成为了近期的热点话题。这一潮流不仅是对比特币网络扩展的重要里程碑&#xff0c;也为新的商业模式和生态系统带来了无限可能。然而&#xff0c;随之而来的是各种挑战…

支付宝支付之SpringBoot整合支付宝入门

支付宝支付 对接流程 申请阿里支付官方企业账号配置应用签约产品获取RSAKey&#xff08;非对称加密&#xff09;必须获得两个加密串&#xff1a;一个公钥&#xff0c;一个密钥SDK功能开发业务对接支付回调支付组件 核心所需的参数 APPID商家私钥支付宝公钥支付回调地址网关…

实战纪实 | 学工平台平行越权

一.账号密码可爆破&#xff08;无验证码&#xff09; 1.学校学工平台用于请假跟每日上报健康信息&#xff0c;登录框如下&#xff1a; 2.经过测试发现这里不存在验证码验证&#xff0c;并且存在初始密码&#xff0c;可以尝试使用默认密码爆破账号&#xff1a; 3.经测试&#x…

【无标题】PHP-parse_str变量覆盖

[题目信息]&#xff1a; 题目名称题目难度PHP-parse_str变量覆盖1 [题目考点]&#xff1a; 变量覆盖指的是用我们自定义的参数值替换程序原有的变量值&#xff0c;一般变量覆盖漏洞需要结合程序的其它功能来实现完整的攻击。 经常导致变量覆盖漏洞场景有&#xff1a;$$&…

自动化测试Selenium(3)

目录 WebDriver相关API 打印信息 打印title 打印url 浏览器的操作 浏览器最大化 设置浏览器的宽,高 操作浏览器的前进, 后退, 刷新 控制浏览器滚动条 键盘事件 键盘单键用法 键盘组合按键用法 鼠标事件 WebDriver相关API 打印信息 打印title 即打印该网址的标题.…

护网行动 | 蓝队应急响应流程概述

了解蓝队应急响应的流程 应急响应通常是指为了应对各种意外事件发生前所做的准备&#xff0c;以及在意外事件发生后所采取的措施。 网络安全应急响应是指对已经发生或可能发送的安全事件进行监控、分析、协调、处理、保护资产安全。 网络安全应急响应主要是为了让人们对网络安全…

idea2023专业版安装破解+maven配置教程

前言 上一篇文章已经介绍了maven在Win10系统的安装配置教程。基于Win10的maven配置环境&#xff0c;本篇文章将介绍idea2023的安装破解教程及maven在idea2023的配置教程&#xff08;同时会将maven在idea2023的配置教程内容补充至上一篇文章&#xff09;。 一、idea2023下载安…