当前位置: 首页 > news >正文

【C++基础】--多态

深入了解多态

  • 一、认识多态
  • 二、定义及实现
    • 构成条件
    • 虚函数重写
    • C++11 override 和 final
      • final:修饰虚函数,表示该虚函数不能再被重写
      • override: 检查派生类虚函数是否重写了基类某个虚函数,如果没有重写编译报错。
  • 三、抽象类
    • 概念
  • 四、多态的实现原理
    • 扩展

在这里插入图片描述

一、认识多态

多态作为面向对象三大特征之一,指的是一个接口可以有多个不同的实现方式。简单说,就是同一个函数或方法调用,可以根据上下文的不同执行不同的功能。在C++中,多态主要是通过基类的指针或引用,来调用子类的重写函数实现。C++中的多态主要是通过虚函数来实现。
示例:

#include <iostream>
using namespace std;class Base {
public:virtual void show() {cout << "Base class show function" << endl;}
};class Derived : public Base {
public:void show() override {cout << "Derived class show function" << endl;}
};int main() {Base* basePtr;Derived derivedObj;basePtr = &derivedObj;basePtr->show();  // 输出:Derived class show functionreturn 0;
}

在上述代码中,通过基类指针basePtr,调用子类derivedObj的show方法。这就是多态。

二、定义及实现

构成条件

在继承中构成多态满足以下条件:
1.必须通过基类的指针或者引用调用虚函数
2. 被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写

在这里插入图片描述

虚函数重写

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

class Person {
public:virtual void BuyTicket() { cout << "买票-全价" << endl; }
};
class Student : public Person {
public:virtual void BuyTicket() { cout << "买票-半价" << endl; }
/*注意:在重写基类虚函数时,派生类的虚函数在不加virtual关键字时,虽然也可以构成重写(因为继承后基类的虚函数被继承下来了在派生类依旧保持虚函数属性),但是该种写法不是很规范,不建议这样使用*/
/*void BuyTicket() { cout << "买票-半价" << endl; }*/
};
void Func(Person& p)
{ p.BuyTicket(); }
int main()
{Person ps;Student st;Func(ps);Func(st);return 0;}

C++11 override 和 final

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

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

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

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

三、抽象类

概念

在虚函数的后面写上=0,则这个虚函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫做接口),抽象类不能实例化出对象。派生类继承后也不能实例化出对象,只有重写纯虚函数,派生类才能实例化出对对象。纯虚函数规范了派生类重写,另外纯虚函数更体现了接口继承。

class Car
{
public:virtual void Drive() = 0;
};
class Benz :public Car
{
public:virtual void Drive(){cout << "Benz-舒适" << endl;}
};
class BMW :public Car
{
public:virtual void Drive(){cout << "BMW-操控" << endl;}
};
void Test()
{Car* pBenz = new Benz;pBenz->Drive();Car* pBMW = new BMW;pBMW->Drive();
}

四、多态的实现原理

多态的实现原理,主要是虚函数、虚函数表和虚函数指针方向。
多态通过虚函数实现。通过虚函数,子类可以重写父类的方法,当通过基类指针或引用调用时,会根据对象的实际类型调用对应的函数实现。
更深层次的原理,是通过虚表(vtable)和虚表指针(vptr)机制实现的。虚表是一个函数指针数组,包含了该类的所有虚函数的地址,而虚表指针存储在对象实例中,指向属于该对象的虚表。

扩展

  • 虚函数和重写:在基类中使用关键字virtual声明虚函数后,在子类中可以重写这个函数
  • 虚表(vtable):每个包含虚函数的类都会有一个虚表(vtable),这个虚表在编译时生成。他包含该类所有虚函数的指针。对于每个类(而不是每个对象),编译器会创建一个唯一的虚表。
  • 虚表指针(vptr):每个包含虚函数的对象实例会有一个隐藏的虚表指针(vptr),他在对象创建时自动初始化,指向该类的虚表。不同类型的对象,其虚表指针会指向不同的虚表。例如
  • 多态的调用机制:当通过基类指针或引用调用虚函数时,程序会通过该类指针或引用找到对应的对象,然后通过虚表指针找到正确的虚表中的函数地址,最终调用适当的函数实现,这样程序能够在运行时决定调用哪一个函数实现。
    实例:
class Base {
public:virtual void show() {std::cout << "Base show" << std::endl;}
};class Derived : public Base {
public:void show() override {std::cout << "Derived show" << std::endl;}
};void demonstratePolymorphism(Base &obj) {obj.show();  // 依赖于实际对象的类型
}int main() {Base b;Derived d;demonstratePolymorphism(b);  // 输出 "Base show"demonstratePolymorphism(d);  // 输出 "Derived show"return 0;
}
http://www.dtcms.com/a/287036.html

相关文章:

  • PortSwigger Labs 之 点击劫持利用
  • Go语言流程控制(if / for)
  • 编程研发工作日记_廖万忠_2016_2017
  • 从零构建监控系统:先“完美设计”还是先“敏捷迭代”?
  • Java Web项目Dump文件分析指南
  • 白话深度学习:一副PPT入门CNN,ResNet和Transformer
  • 闲庭信步使用图像验证平台加速FPGA的开发:第二十三课——图像直方图和灰度图像叠加的FPGA实现
  • 14-链路聚合
  • ZeroMQ中的REQ/REP模式:分布式系统的同步调用之道
  • JavaSE -- 数据操作流
  • 比亚迪古德伍德亮相:从技术突破到文化对话
  • 【53】MFC入门到精通——MFC串口助手(二)---通信版(发送数据 、发送文件、数据转换、清空发送区、打开/关闭文件),附源码
  • SDIO协商,枚举,CMD等概念
  • SSM框架——Day4
  • 文件管理-文件控制块和索引节点
  • 深入解析Linux文件描述符:原理、机制与应用实践
  • 光伏系统遮挡分析与设计优化策略
  • 网络基础12--可靠性概述及要求
  • b-up:Enzo_Mi:深度学习基础知识
  • 回归预测 | MATLAB实现SA-BP模拟退火算法优化BP神经网络多输入单输出回归预测
  • 7.19 pq | 并查集模板❗|栈循环|数组转搜索树
  • CCF编程能力等级认证GESP—C++4级—20250628
  • Nestjs框架: 关于controller中的常用装饰器
  • 3.3 参数传递方式
  • 写case杂记
  • Glary Utilities(系统优化工具) v6.20.0.24 专业便携版
  • JavaSE -- 数组详细讲解(数组介绍,Arrays常用方法,二维数组创建)
  • Redis学习其三(订阅发布,主从复制,哨兵模式)
  • 优迅股份IPO隐忧:毛利水平“两连降”,研发费用率不及行业均值
  • decltype是什么,什么作用?