当前位置: 首页 > 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.xdnf.cn/news/1146169.html

相关文章:

  • ThreadLocal 在 Spring 与数据库交互中的应用笔记
  • 北京-4年功能测试2年空窗-报培训班学测开-第五十四天
  • Kubernetes Pod深度理解
  • 大模型格式
  • 外部DLL创建及使用
  • UVC for USBCamera in Android - 篇二
  • 腾讯 ChatBI 调研
  • 如何为“地方升学导向型”语校建模?Prompt 框架下的宇都宫日建工科专门学校解析(7 / 500)
  • Java HashMap高频面试题深度解析
  • 对于编码电机-520直流减速电机
  • 【AI News | 20250717】每日AI进展
  • 3.3 参数传递方式
  • 应用集成体系深度解析:从数据互通到流程协同
  • 20250718【顺着234回文链表做两题反转】Leetcodehot100之20692【直接过12明天吧】今天计划
  • Machine Learning HW2 report:语音辨识(Hongyi Lee)
  • 操作系统-处理机调度和死锁进程同步
  • 全球天气预报5天(经纬度版)免费API接口教程
  • HarmonyOS-ArkUI Web控件基础铺垫4--TCP协议- 断联-四次挥手解析
  • 70 gdb attach $pid, process 2021 is already traced by process 2019
  • postman接口测试,1个参数有好几个值的时候如何测试比较简单快速?
  • PPIO × Lemon AI:一键解锁全流程自动化开发能力
  • 【DataWhale】快乐学习大模型 | 202507,Task03笔记
  • 机械材料计算软件,快速核算重量
  • Python暑期学习笔记5
  • Excel导出实战:从入门到精通 - 构建专业级数据报表的完整指南
  • Nestjs框架: 基于TypeORM的多租户功能集成和优化
  • 多线程-4-线程池
  • 锁步核,为什么叫锁步核?
  • Android性能优化之启动优化
  • leetcode15.三数之和题解:逻辑清晰带你分析