「C++系列」多态

news2024/11/15 15:53:41

【人工智能教程】,前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。

点击跳转到网站:【人工智能教程】

文章目录

  • 一、多态
    • 1. 虚函数(Virtual Functions)
    • 2. 抽象基类(Abstract Base Classes, ABCs)
  • 二、多态应用场景
    • 1. 图形绘制系统
    • 2. 案例代码
    • 3. 解释
  • 三、虚函数、纯虚函数
    • 1. 虚函数(Virtual Functions)
    • 2. 纯虚函数(Pure Virtual Functions)
  • 四、相关链接

一、多态

C++中的多态性(Polymorphism)是一种面向对象编程的特性,它允许我们通过基类指针或引用调用派生类的方法。多态性主要分为两种:编译时多态(静态多态)和运行时多态(动态多态)。在C++中,我们通常关注的是运行时多态,它通过虚函数(virtual functions)和抽象基类(abstract base classes)实现。

1. 虚函数(Virtual Functions)

虚函数是实现多态的基础。当一个基类中的函数被声明为虚函数时,任何从这个基类派生出的子类都可以重写(override)这个函数。通过基类指针或引用调用虚函数时,如果指针或引用实际指向的是派生类的对象,那么调用的将是派生类中的重写版本,而不是基类中的原始版本。

#include <iostream>
using namespace std;

class Base {
public:
    virtual void show() {
        cout << "Base class show()" << endl;
    }
    virtual ~Base() {} // 虚析构函数,确保通过基类指针删除派生类对象时,能调用到派生类的析构函数
};

class Derived : public Base {
public:
    void show() override { // override关键字是C++11引入的,用于明确表示意图,不是必需的
        cout << "Derived class show()" << endl;
    }
};

int main() {
    Base* bptr;
    Derived d;
    bptr = &d;
    bptr->show(); // 输出:Derived class show(),因为bptr实际指向Derived类的对象
    return 0;
}

2. 抽象基类(Abstract Base Classes, ABCs)

抽象基类是一种特殊的类,它至少包含一个纯虚函数(Pure Virtual Functions)。纯虚函数是在函数声明后加上= 0来定义的,它要求任何从该基类派生的类都必须实现这个函数。抽象基类不能被实例化,因为它至少有一个函数是未定义的。

#include <iostream>
using namespace std;

class Shape {
public:
    virtual void draw() const = 0; // 纯虚函数
    virtual ~Shape() {}
};

class Circle : public Shape {
public:
    void draw() const override {
        cout << "Drawing Circle" << endl;
    }
};

class Rectangle : public Shape {
public:
    void draw() const override {
        cout << "Drawing Rectangle" << endl;
    }
};

int main() {
    Shape* shape1 = new Circle();
    Shape* shape2 = new Rectangle();
    shape1->draw(); // 调用Circle的draw()
    shape2->draw(); // 调用Rectangle的draw()

    delete shape1;
    delete shape2;
    return 0;
}

二、多态应用场景

C++中的多态性主要用于实现接口的统一性,使得不同类的对象可以通过相同的接口(即基类中的虚函数)来执行各自特有的操作。这种特性在多种应用场景中都非常有用,比如图形界面编程、事件处理、数据库操作等。下面我将给出一个具体的案例代码,展示多态性在图形界面编程中的应用。

1. 图形绘制系统

假设我们有一个图形绘制系统,需要支持多种图形的绘制,如圆形、矩形、三角形等。每种图形都有自己的绘制方法,但我们希望通过一个统一的接口来调用这些绘制方法。

2. 案例代码

首先,我们定义一个Shape基类,它包含一个纯虚函数draw(),表示图形的绘制方法。然后,我们定义几个派生类,如CircleRectangleTriangle,它们分别继承自Shape类并实现draw()方法。

#include <iostream>
#include <vector>
#include <memory>

// 抽象基类
class Shape {
public:
    virtual void draw() const = 0; // 纯虚函数
    virtual ~Shape() {} // 虚析构函数
};

// 圆形类
class Circle : public Shape {
public:
    void draw() const override {
        std::cout << "Drawing Circle" << std::endl;
    }
};

// 矩形类
class Rectangle : public Shape {
public:
    void draw() const override {
        std::cout << "Drawing Rectangle" << std::endl;
    }
};

// 三角形类
class Triangle : public Shape {
public:
    void draw() const override {
        std::cout << "Drawing Triangle" << std::endl;
    }
};

// 图形绘制系统
class GraphicsSystem {
private:
    std::vector<std::unique_ptr<Shape>> shapes; // 使用智能指针管理资源

public:
    void addShape(std::unique_ptr<Shape> shape) {
        shapes.push_back(std::move(shape));
    }

    void drawAllShapes() const {
        for (const auto& shape : shapes) {
            shape->draw(); // 多态调用
        }
    }
};

int main() {
    GraphicsSystem gs;

    // 添加图形到系统中
    gs.addShape(std::make_unique<Circle>());
    gs.addShape(std::make_unique<Rectangle>());
    gs.addShape(std::make_unique<Triangle>());

    // 绘制所有图形
    gs.drawAllShapes();

    return 0;
}

3. 解释

  1. 基类与派生类Shape是基类,定义了所有图形都应该有的draw()方法(纯虚函数)。CircleRectangleTriangle是派生类,分别实现了draw()方法。
  2. 图形绘制系统GraphicsSystem类管理一个Shape对象的集合,并使用std::vector<std::unique_ptr<Shape>>来存储这些对象。这样做的好处是可以自动管理内存(通过智能指针),并且可以利用多态性通过基类指针或引用来调用派生类的draw()方法。
  3. 多态性:在drawAllShapes()方法中,通过遍历shapes集合并使用shape->draw()来调用每个图形的draw()方法。由于draw()是虚函数,因此实际调用的是对象所属类的draw()实现。

三、虚函数、纯虚函数

C++ 中的虚函数(Virtual Functions)和纯虚函数(Pure Virtual Functions)是面向对象编程中多态性的重要组成部分。它们允许通过基类指针或引用来调用派生类中的成员函数,从而实现接口的统一性和功能的多样性。

1. 虚函数(Virtual Functions)

虚函数是基类中声明为 virtual 的成员函数。这意味着该函数在派生类中可能有不同的实现。当通过基类指针或引用调用虚函数时,如果指针或引用实际上指向的是派生类的对象,那么将调用派生类中重写(Override)的虚函数版本,而不是基类中的原始版本。

示例代码

#include <iostream>

class Base {
public:
    virtual void show() {
        std::cout << "Base class show()" << std::endl;
    }
    virtual ~Base() {} // 虚析构函数,确保通过基类指针删除派生类对象时,能调用到派生类的析构函数
};

class Derived : public Base {
public:
    void show() override { // override是C++11的关键字,表示重写基类的虚函数
        std::cout << "Derived class show()" << std::endl;
    }
};

int main() {
    Base* bptr = new Derived(); // 基类指针指向派生类对象
    bptr->show(); // 调用Derived类的show()
    delete bptr; // 释放内存
    return 0;
}

2. 纯虚函数(Pure Virtual Functions)

纯虚函数是在基类中声明为 virtual 并使用 = 0 语法定义的函数。纯虚函数没有函数体(即没有大括号内的实现代码),并且要求任何从该基类派生的类都必须提供该函数的实现,除非该派生类也是抽象类(即也包含纯虚函数)。包含纯虚函数的类被称为抽象基类(Abstract Base Class, ABC),它不能被实例化。

示例代码

#include <iostream>

class Shape {
public:
    virtual void draw() const = 0; // 纯虚函数
    virtual ~Shape() {} // 虚析构函数
};

class Circle : public Shape {
public:
    void draw() const override {
        std::cout << "Drawing Circle" << std::endl;
    }
};

int main() {
    // Shape s; // 错误,Shape是抽象类,不能实例化
    Circle c;
    c.draw(); // 调用Circle的draw()
    return 0;
}
  • 虚函数:允许在派生类中重写,通过基类指针或引用调用时,实际调用的是派生类中的实现。
  • 纯虚函数:没有实现体,强制要求派生类提供实现,包含纯虚函数的类不能被实例化。

在这里插入图片描述

四、相关链接

  1. Visual Studio Code下载地址
  2. Sublime Text下载地址
  3. 「C++系列」C++简介、应用领域
  4. 「C++系列」C++ 基本语法
  5. 「C++系列」C++ 数据类型
  6. 「C++系列」C++ 变量类型
  7. 「C++系列」C++ 变量作用域
  8. 「C++系列」C++ 常量知识点-细致讲解
  9. 「C++系列」C++ 修饰符类型
  10. 「C++系列」一篇文章说透【存储类】
  11. 「C++系列」一篇文章讲透【运算符】
  12. 「C++系列」循环
  13. 「C++系列」判断
  14. 「C++系列」函数/内置函数
  15. 「C++系列」数字/随机数
  16. 「C++系列」数组
  17. 「C++系列」字符串
  18. 「C++系列」指针
  19. 「C++系列」引用
  20. 「C++系列」日期/时间
  21. 「C++系列」输入/输出
  22. 「C++系列」数据结构
  23. 「C++系列」vector 容器
  24. 「C++系列」类/对象
  25. 「C++系列」继承
  26. 「C++系列」重载运算符/重载函数

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

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

相关文章

多线程——概念

​ 进程 操作系统中进行资源分配的基本单位&#xff0c;进程就是进行中的程序&#xff0c;处于运行过程中的。 三个基本特征&#xff1a; 独立性&#xff1a;进程是独立运行&#xff0c;独立获取资源&#xff0c;独立接收调度的基本单。没有进程本身的统一&#xff0c;其他…

无人机专业大学生参与无人机飞手执照培训技术分析

无人机专业的大学生参与无人机飞手执照培训&#xff0c;不仅是获取职业资质的重要步骤&#xff0c;也是提升专业技能和就业竞争力的关键。以下是对无人机专业大学生参与无人机飞手执照培训的技术分析&#xff1a; 1. 培训内容的全面性 无人机飞手执照培训涵盖了从无人机基础知…

数据取证:GetData Forensic Explorer,强大的文件分析和数据恢复工具

天津鸿萌科贸发展有限公司是 GetData 公司 Forensic Explorer 电子数据取证调查软件的授权代理商。 Forensic Explorer 是一款适合新手和经验丰富的调查员使用的取证工具&#xff0c;它将灵活易用的图形界面与高级排序、过滤、关键词搜索、数据恢复和脚本技术相结合。可以快速处…

5个惊人策略:打造完美的企业内部知识库

引言&#xff1a; 在这个快速变化的商业环境中&#xff0c;拥有一个结构化和高效的内部知识库不再是可选项&#xff0c;而是企业成功的必需品。SaaS&#xff08;Software as a Service&#xff0c;软件即服务&#xff09;平台的兴起&#xff0c;为企业打造这样的内部知识库提供…

一文带你springai+ollama实现chat

Spring AI Spring AI 项目旨在简化开发集成了人工智能功能的应用程序&#xff0c;而不增加不必要的复杂性。该项目从一些著名的 Python 项目中汲取灵感&#xff0c;例如 LangChain 和 LlamaIndex&#xff0c;但 Spring AI 并不是这些项目的直接移植。该项目的创立基于这样的信念…

龙芯+FreeRTOS+LVGL实战笔记(新)——02准备工程和驱动文件

本专栏是笔者另一个专栏《龙芯RT-ThreadLVGL实战笔记》的姊妹篇&#xff0c;主要的区别在于实时操作系统的不同&#xff0c;章节的安排和任务的推进保持一致&#xff0c;并对源码做了完善与优化&#xff0c;各位可以先到本人主页下去浏览另一专栏的博客列表&#xff08;目前已撰…

基于Java的图书推荐系统的设计与实现(论文+源码)_kaic

摘要 随着中国城市现代化的发展进程越来越快&#xff0c;网络信息无论是数量还是传播速度早已超过纸质传媒&#xff0c;图书推荐系统是否能提供高效和优质的服务己成为图书阅读的重要环节。因此&#xff0c;需要构建一套基于Java编程语言的图书推荐系统。本系统使用Java语言和S…

嵌入式全栈开发学习笔记---shell脚本

目录 shell脚本有什么用&#xff1f; 第一个shell脚本 shell基本语法 shell变量 shell三种变量 环境级变量 用户级变量 系统级变量 在shell脚本中进行数学运算 shell数组 基本数组 关联数组 流程控制 If语句 Case语句 循环语句 While语句 For语句 上节我们学…

这可能是你在编程学习中最容易忽视的一课

引言 在编程学习的道路上&#xff0c;你是否曾感到困惑&#xff0c;面对着一堆复杂的术语和工具&#xff0c;不知道从何下手&#xff1f;刚开始编程时&#xff0c;是不是总觉得像走进了一片迷雾&#xff1f;别担心&#xff0c;你并不孤单。这篇文章将为你揭示“计算机教育中缺…

深度学习资料集合

社区推荐 AIQ 是一个专注于人工智能和机器学习的交流平台&#xff0c;旨在推动行业内的知识分享与技术交流。 专知 是一个聚焦于前沿科技和多领域知识的平台&#xff0c;提供丰富的文章和讨论&#xff0c;使用户能够深入理解机器学习及其应用。 DataTau DataTau 是一个数据…

Facebook与区块链:构建更安全的社交网络生态

随着数字化时代的不断推进&#xff0c;社交网络的安全性和隐私保护成为了用户最为关注的问题之一。Facebook&#xff0c;作为全球领先的社交媒体平台&#xff0c;正在探索如何利用区块链技术来增强其平台的安全性和透明度。这一探索不仅是对现有技术的补充&#xff0c;更是对未…

Android运行时权限详解

文章目录 Android运行时权限详解Android权限机制详解在程序运行时申请权限 Android运行时权限详解 Android的权限机制并不是什么新鲜事物&#xff0c;从系统的第一个版本开始就已经存在了。但其实之前Android的权限机制在保护用户安全和隐私等方面起到的作用比较有限&#xff…

利用OSINT追踪勒索组织活动

0X00前言 众所周知&#xff0c;勒索组织一直是臭名昭著的代名词。在当今网络世界上时时刻刻都存在着勒索软件的身影。正所谓&#xff0c;不知攻&#xff0c;焉知防。我们可以更据OSINT的方法&#xff0c;去追踪分析各大勒索组织的活动&#xff0c;以及状态。为应对可能的勒索攻…

【Python基础】元组类型

本文收录于 《Python编程入门》专栏&#xff0c;从零基础开始&#xff0c;分享一些Python编程基础知识&#xff0c;欢迎关注&#xff0c;谢谢&#xff01; 文章目录 一、前言二、Python 元组2.1 创建特殊元组2.2 访问元组2.3 删除元组2.4 元组截取2.5 元组运算符2.6 元组内置函…

佰朔资本:9月券商金股出炉,这类股获机构力推

现在&#xff0c;券商新一批月度金股近期连续出炉。到9月1日&#xff0c;14家券商发布9月月度金股&#xff0c;举荐的104只金股会集分布在电子、机械设备、传媒、汽车等工作中。从个股来看&#xff0c;比亚迪、我国安全、阳光电源获2家以上券商共同举荐。别的&#xff0c;北方华…

30 静态路由

静态路由 一、配置静态路由 &#xff08;一&#xff09;静态路由特点 ​ 主要特点&#xff1a; ​ 由管理员手工配置&#xff0c;为单向条目通信双方的边缘路由器都需要指定&#xff0c;否则会导致数据包有去无回 &#xff08;二&#xff09;静态路由配置 ​ 使用ip rout…

开学季儿童护眼台灯怎么选择?盘点央视公布十大护眼灯!

随着年级的升高和学习内容的增加&#xff0c;学生的休闲娱乐时间逐渐减少&#xff0c;相反&#xff0c;他们在书桌前度过的时间却越来越多。近年来&#xff0c;由于电子产品的广泛使用&#xff0c;我国青少年的用眼负担显著增加。据权威机构预测&#xff0c;到2050年&#xff0…

ActiViz实战:使用vtkDistanceWidget实现两点测距功能

文章目录 一、效果图预览二、实现步骤三、C#完整实例代码一、效果图预览 二、实现步骤 1、通过vtkCellPicker拾取点坐标 2、通过vtkDistanceRepresentation2D设置起始点和结束点位置 3、通过vtkDistanceRepresentation2D的GetAxis()获取vtkAxisActor2D对象,并设置连线的样式 …

前端安全:如何防范跨站脚本攻击(XSS)

聚沙成塔每天进步一点点 本文回顾 ⭐ 专栏简介前端安全&#xff1a;如何防范跨站脚本攻击 (XSS)1. 引言2. 什么是跨站脚本攻击 (XSS)&#xff1f;2.1 XSS的分类 3. XSS攻击的危害4. XSS的常见攻击手法4.1 注入恶意脚本4.2 伪造表单和链接4.3 操纵DOM结构 5. 如何防范XSS攻击5.1…

Git使用(命令+idea快捷)

目录 一、概述 1.什么是Git 2.Git能干什么 3.简介 4.下载和安装 二、Git代码托管服务 1.常用的Git代码托管服务 2.使用码云代码托管服务 三、Git全局设置&#xff08;常用命令&#xff09; 1.命令 2.实现 四、获取Git仓库&#xff08;常用命令&#xff09; 1.两种方…