C++实用教程(四):面向对象核心多态 笔记

news2024/10/7 10:18:26

推荐B站视频:C++现代实用教程(四):面向对象核心多态_哔哩哔哩_bilibiliicon-default.png?t=N7T8https://www.bilibili.com/video/BV15v4y1M7fF/?spm_id_from=333.999.0.0&vd_source=a934d7fc6f47698a29dac90a922ba5a3

本项目通用的tasks.json文件和launch.json

  • tasks.json
{
    "version": "2.0.0",
    "options": {
        "cwd": "${workspaceFolder}/build"
    },
    "tasks": [
        {
            "type": "shell",
            "label": "cmake",
            "command": "cmake",
            "args": [
                ".."
            ]
        },
        {
            "label": "make",
            "group": "build",
            "command": "make",
            "args": [],
            "problemMatcher": []
        },
        {
            "label": "Build",
            "dependsOrder": "sequence",
            "dependsOn": [
                "cmake",
                "make"
            ]
        },
        {
            "type": "cppbuild",
            "label": "C/C++: g++ 生成活动文件",
            // "command": "/usr/bin/g++",
            "command": "D://mingw64//bin//g++.exe",
            "args": [
                "-fdiagnostics-color=always",
                "-g",
                "-o",
                "${workspaceFolder}/bin/app.exe",
                // "-finput-charset=UTF-8",
                /*
                    -fexec-charset指定输入文件的编码格式
                    -finput-charset指定生成可执行的编码格式,
                */
                "-finput-charset=GBK",  // 处理mingw中文编码问题
                "-fexec-charset=GBK"
            ],
            "options": {
                "cwd": "${workspaceFolder}"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "detail": "D://mingw64//bin//g++.exe"
        }
    ]
}
  • launch.json
{
    // 使用 IntelliSense 了解相关属性。 
    // 悬停以查看现有属性的描述。
    // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) 启动",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/bin/app.exe",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "setupCommands": [
                {
                    "description": "为 gdb 启用整齐打印",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true,
                },
            ],
            "preLaunchTask": "Build",
            "miDebuggerPath": "D://mingw64//bin//gdb.exe", // 修改为你的 gdb 路径
        },
    ]
}
  • CMakeLists.txt
​cmake_minimum_required(VERSION 3.28.0)
project(project)
include_directories(${PROJECT_SOURCE_DIR}/include)
aux_source_directory(${PROJECT_SOURCE_DIR}/src SRC_LIST)

add_executable(app main.cpp ${SRC_LIST})
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

​

C++的面向对象与很多其他的面向对象语言有很多不同,本质的原因是在于C++是一门极其重视性能的编程语言

>>多态是面向对象的核心

  • 这一点对于C++来说也不例外
  • 面向对象三大特性为:封装、继承、多态
    • 本人不是很喜欢C++的继承,其实是不喜欢继承
    • 封装和继承基本上是为多态而准备的
  • 面向对象是使用多态性获得对系统中每个源代码依赖项的绝对控制的能力的(大牛说的)
  • 高内聚、低耦合是程序设计的目标(无论是否面向对象,),而多态是实现高内聚,低耦合的基础

>>目录

    1.多态与静态绑定

    2.虚函数与动态绑定

    3.多态对象的应用场景与大小

    4.Override与Final

    5.Overloading与多态

    6.析构函数与多态

    7.Dynamic_cast类型转换

    8.typeid操作符

    9.纯虚函数与抽象类

    10.接口式抽象类

第一节:多态与静态绑定

>>多态:

  • 在编程语言和类型论中,多态(英语:polymorphism)指为不同数据类型的实体提供统一的接口
  • 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数

>>静态绑定:将名称绑定到一个固定的函数定义,然后在每次调用该名称时执行该定义,这个也是常态执行的方式

  • shape.h 
#ifndef SHAPE_H
#define SHAPE_H
#include <string>
#include <string_view>
#include <iostream>
class Shape{
public:
    Shape() = default;
    ~Shape() = default;
    Shape(std::string_view name);
    void draw() const {
        std::cout<<"Shape Drawing "<<m_name<<std::endl;
    }
protected:
    std::string m_name;
};
#endif
  • shape.cpp
#include "shape.h"

Shape::Shape(std::string_view name) : m_name(name){

}
  • rectangle.h
#ifndef RECTANGLE_H
#define RECTANGLE_H
#include <string>
#include <string_view>
#include <iostream>
#include "shape.h"
class Rectangle:public Shape{
public:
    Rectangle() = default;
    ~Rectangle() = default;
    Rectangle(double x,double y,std::string_view name);

    void draw() const {
        std::cout<<"Rectangle Drawing "<<m_name<<" with x: "<<get_x()<<",y: "<<get_y()<<std::endl;
    }
protected:
    double get_x() const{
        return m_x;
    }
    double get_y() const{
        return m_y;
    }
private:
    double m_x{0.0};
    double m_y{0.0};
};
#endif
  • rectangle.cpp
#include "rectangle.h"

Rectangle::Rectangle(double x, double y,std::string_view name)
    : Shape(name),m_x(x),m_y(y)
{

}
  • square.h
#ifndef SQUARE_H
#define SQUARE_H
#include "rectangle.h"
class Square:public Rectangle{
public:
    Square() = default;
    ~Square() = default;
    Square(double x,std::string_view name);

    void draw() const {
        std::cout<<"Square Drawing "<<m_name<<" with x: "<<get_x()<<std::endl;
    }
};
#endif
  • square.cpp
#include "square.h"

Square::Square(double x, std::string_view name)
    : Rectangle(x,x,name)
{
}
  • main.cpp
#include <iostream>
#include "square.h"
#include "rectangle.h"
#include "shape.h"
using namespace std;

// Shape -> Rectangle -> Square
// draw()
void test1() {
    // 静态绑定的不足
    Shape s1("Shape1");
    s1.draw();// Shape Drawing Shape1

    Rectangle r1(1.0,2.0,"Rectangle1");
    r1.draw();// Rectangle Drawing Rectangle1 with x: 1,y: 2

    Square sq1(3.0,"Square1");
    sq1.draw();// Square Drawing Square1 with x: 3

    // Base Pointer
    Shape* shape_ptr = &s1;
    shape_ptr->draw();// Shape Drawing Shape1
    shape_ptr = &r1;
    shape_ptr->draw();// Shape Drawing Rectangle1
    shape_ptr = &sq1;
    shape_ptr->draw();// Shape Drawing Square1
}

int main(int argc,char* argv[]) {
    test1();
    cout<<"over~"<<endl;
    return 0;
}
  •  执行结果:
PS D:\Work\C++UserLesson\cppenv\static_bind\build> ."D:/Work/C++UserLesson/cppenv/static_bind/bin/app.exe"
Shape Drawing Shape1
Rectangle Drawing Rectangle1 with x: 1,y: 2
Square Drawing Square1 with x: 3
Shape Drawing Shape1
Shape Drawing Rectangle1
Shape Drawing Square1
over~
PS D:\Work\C++UserLesson\cppenv\static_bind\build>

第二节:虚函数与动态绑定

>>动态绑定

  • 实现继承
  • 父类、子类需要动态绑定的函数设置为虚函数
  • 创建父类指针/引用(推荐指针)指向子类对象,然后调用

>>虚函数

  • 虚函数是应在派生类中重新定义的成员函数
  • 关键字为virtual

通过例子来实现多态

  • shape.h
#ifndef SHAPE_H
#define SHAPE_H
#include <string>
#include <string_view>
#include <iostream>
class Shape{
public:
    Shape() = default;
    ~Shape() = default;
    Shape(std::string_view name);
    virtual void draw() const {
        std::cout<<"Shape Drawing "<<m_name<<std::endl;
    }
protected:
    std::string m_name;
};
#endif
  • shape.cpp
#include "shape.h"

Shape::Shape(std::string_view name) : m_name(name){

}
  • rectangle.h
#ifndef RECTANGLE_H
#define RECTANGLE_H
#include <string>
#include <string_view>
#include <iostream>
#include "shape.h"
class Rectangle:public Shape{
public:
    Rectangle() = default;
    ~Rectangle() = default;
    Rectangle(double x,double y,std::string_view name);

    virtual void draw() const {
        std::cout<<"Rectangle Drawing "<<m_name<<","<<"x: "<<get_x()<<",y: "<<get_y()<<std::endl;
    }
protected:
    double get_x() const{
        return m_x;
    }
    double get_y() const{
        return m_y;
    }
private:
    double m_x{0.0};
    double m_y{0.0};
};
#endif
  • rectangle.cpp
#include "rectangle.h"

Rectangle::Rectangle(double x, double y,std::string_view name)
    : Shape(name),m_x(x),m_y(y)
{

}
  • square.h
#ifndef SQUARE_H
#define SQUARE_H
#include "rectangle.h"
class Square:public Rectangle{
public:
    Square() = default;
    ~Square() = default;
    Square(double x,std::string_view name);

    void draw() const {
        std::cout<<"Square Drawing "<<m_name<<" with x: "<<get_x()<<std::endl;
    }
};
#endif
  • square.cpp
#include "square.h"

Square::Square(double x, std::string_view name)
    : Rectangle(x,x,name)
{
}
  • 执行结果:
PS D:\Work\C++UserLesson\cppenv\dynamic_bind\bin> ."D:/Work/C++UserLesson/cppenv/dynamic_bind/bin/app.exe"
Shape Drawing Shape1
Rectangle Drawing Rectangle1,x: 1,y: 2
Square Drawing Square1 with x: 3
over~
PS D:\Work\C++UserLesson\cppenv\dynamic_bind\bin>

第三节:多态对象的应用场景与大小

(1)多态的两个应用场景

  • 函数
  • 存储进入Collections

(2)多态与Collection

  • 可以存储值类型(并不满足多态)
  • 可以存储指针类型
  • 不可以存储引用

(3)通过例子来

  • 多态的两大应用场景

 注意:这里的源文件和头文件和第二节的一样!

(1)Base Pointers

#include <iostream>
#include "square.h"
#include "rectangle.h"
#include "shape.h"
using namespace std;

void draw_shape(Shape* s) {
    s->draw();
}

// Shape -> Rectangle -> Square
// draw()
void test1() {
    Shape s1("Shape1");
    Rectangle r1(1.0,2.0,"Rectangle1");
    Square sq1(3.0,"Square1");

    // Base Pointers
    Shape* shape_ptr = &s1;
    draw_shape(shape_ptr);
    shape_ptr = &r1;
    draw_shape(shape_ptr);
    shape_ptr = &sq1;
    draw_shape(shape_ptr);
}

int main(int argc,char* argv[]) {
    test1();
    cout<<"over~"<<endl;
    return 0;
}

执行结果:

PS D:\Work\C++UserLesson\cppenv\dynamic_application\bin> ."D:/Work/C++UserLesson/cppenv/dynamic_application/bin/app.exe"
Shape Drawing Shape1
Rectangle Drawing Rectangle1,x: 1,y: 2
Square Drawing Square1 with x: 3
over~
PS D:\Work\C++UserLesson\cppenv\dynamic_application\bin>

 (2)多态与Collection

  • 可以存储值类型(并不满足多态)
#include <iostream>
#include "square.h"
#include "rectangle.h"
#include "shape.h"
using namespace std;

void draw_shape(Shape* s) {
    s->draw();
}

// Shape -> Rectangle -> Square
// draw()
void test1() {
    Shape s1("Shape1");
    Rectangle r1(1.0,2.0,"Rectangle1");
    Square sq1(3.0,"Square1");

    // collection 
    cout<<"*********collection*********"<<endl;
    Shape shapes[]{s1,r1,sq1}; // 不符合多态
    for(Shape &s:shapes) {
        s.draw();
    }
}

int main(int argc,char* argv[]) {
    test1();
    cout<<"over~"<<endl;
    return 0;
}

执行结果:

PS D:\Work\C++UserLesson\cppenv\dynamic_application\bin> ."D:/Work/C++UserLesson/cppenv/dynamic_application/bin/app.exe"
*********collection*********
Shape Drawing Shape1
Shape Drawing Rectangle1
Shape Drawing Square1
over~
PS D:\Work\C++UserLesson\cppenv\dynamic_application\bin>

(2)多态与Collection

  • 可以存储指针类型
#include <iostream>
#include "square.h"
#include "rectangle.h"
#include "shape.h"
using namespace std;

void draw_shape(Shape* s) {
    s->draw();
}

// Shape -> Rectangle -> Square
// draw()
void test1() {
    Shape s1("Shape1");
    Rectangle r1(1.0,2.0,"Rectangle1");
    Square sq1(3.0,"Square1");

    // Pointer
    cout<<"*********Pointer*********"<<endl;
    Shape* shapes_ptr[]{&s1,&r1,&sq1};
    for(Shape* s:shapes_ptr) {
        s->draw();
    }
}

int main(int argc,char* argv[]) {
    test1();
    cout<<"over~"<<endl;
    return 0;
}

执行结果:

PS D:\Work\C++UserLesson\cppenv\dynamic_application\bin> ."D:/Work/C++UserLesson/cppenv/dynamic_application/bin/app.exe"
*********Pointer*********
Shape Drawing Shape1
Rectangle Drawing Rectangle1,x: 1,y: 2
Square Drawing Square1 with x: 3
over~
PS D:\Work\C++UserLesson\cppenv\dynamic_application\bin>

 (2)多态与Collection

  • 不可以存储引用
#include <iostream>
#include "square.h"
#include "rectangle.h"
#include "shape.h"
using namespace std;

void draw_shape(Shape* s) {
    s->draw();
}

// Shape -> Rectangle -> Square
// draw()
void test1() {
    Shape s1("Shape1");
    Rectangle r1(1.0,2.0,"Rectangle1");
    Square sq1(3.0,"Square1");

    // Shape ref 
    // cout<<"*********collection*********"<<endl;
    Shape &shape_ref[]{s1,r1,sq1}; //error 不允许使用引用的数组
}

int main(int argc,char* argv[]) {
    test1();
    cout<<"over~"<<endl;
    return 0;
}

 

未完待续~

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

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

相关文章

TMS智慧园区物流系统:提升化工园区管理效率的最佳选择

在化工行业园区中&#xff0c;企业面临着诸多痛点&#xff0c;如人工管理流程复杂、园区堵车、园区安全管理不到位、设备资产管理缺失、环境管理混乱无章、数据无法追溯等。这些问题不仅影响企业的生产效率和经济效益&#xff0c;还可能对员工的生命安全和环境造成潜在威胁。为…

uniapp封装公共的方法或者数据请求方法

仅供自己参考&#xff0c;不是每个页面都用到这个方法&#xff0c;所以我直接在用到的页面引用该公用方法&#xff1a; 1、新建一个util.js文件 export const address function(options){return new Promise((resolve,reject)>{uni.request({url:"https://x.cxniu.…

C# 命名管道管道NamedPipeServerStream使用

NamedPipeServerStream 是 .NET Framework 和 .NET Core 中提供的一个类&#xff0c;用于创建和操作命名管道的服务器端。命名管道是一种在同一台计算机上或不同计算机之间进行进程间通信的机制。 命名管道允许两个或多个进程通过共享的管道进行通信。其中一个进程充当服务器&…

CentOS网络配置进阶:深入研究network服务和NetworkManager

前言 如果你正在使用CentOS系统,并且想要深入了解网络管理和配置,那么本文肯定适合你!在这篇文章中,作者深入探讨了CentOS中的两种网络管理方式:network服务和NetworkManager。通过详实的讲解和实用的示例,你将会学习到如何使用这两种工具来管理网络接口、配置IP地址、网…

外贸邮件群发软件有哪些?邮件群发的系统?

外贸邮件群发软件哪个比较好&#xff1f;外贸开发信软件推荐&#xff1f; 对于许多外贸企业来说&#xff0c;邮件营销是一种非常有效的推广方式。那么&#xff0c;外贸邮件群发软件就成为了必备的工具。蜂邮EDM将为你揭秘几款主流的外贸邮件群发软件&#xff0c;助你更好地开展…

用javadoc生成springboot的文档

概述&#xff1a;生成 Spring Boot 项目的 JavaDoc 文档与生成普通的 Java 项目类似。 目录 第一步&#xff1a;创建一个springboot项目 第二步&#xff1a;编写pom文件 第三步&#xff1a;运行 Maven 命令生成 JavaDoc 第四步&#xff1a;查看结果 第一步&#xff1a;创建…

海外媒体发稿:出口贸易媒体发稿推广8种方法让您事半功倍-华媒舍

通过出口贸易媒体发稿可以帮助企业拓展市场、提升知名度&#xff0c;从而取得更好的出口贸易业绩。在进行媒体发稿时&#xff0c;需要确定目标受众&#xff0c;编写吸引人的标题&#xff0c;提供有价值的内容&#xff0c;并选择合适的媒体平台和发布时间。通过持续改进和优化&a…

自然语言NLP学习

2-7 门控循环单元&#xff08;GRU&#xff09;_哔哩哔哩_bilibili GRU LSTM 双向RNN CNN 卷积神经网络 输入层 转化为向量表示 dropout ppl 标量 在物理学和数学中&#xff0c;标量&#xff08;Scalar&#xff09;是一个只有大小、没有方向的量。它只用一个数值就可以完全…

docker之部署青龙面板

青龙面板是一个用于管理和监控 Linux 服务器的工具&#xff0c;具有定时运行脚本任务的功能。在实际情况下也可以用于一些定期自动签到等任务脚本的运行。 本次记录下简单的安装与使用&#xff0c;请提前安装好docker&#xff0c;参考之前的文章。 一、安装部署 1、拉取镜像 # …

小迪安全21WEB 攻防-JavaWeb 项目JWT 身份攻击组件安全访问控制

#知识点&#xff1a; 1、JavaWeb 常见安全及代码逻辑 2、目录遍历&身份验证&逻辑&JWT 3、访问控制&安全组件&越权&三方组件 Java&#xff1a;大部分都是第三方插件出现漏洞 webgoat的搭建&#xff1a;——java靶场 JDK版本要求&#xff1a;11.0…

图形绘制QGraphicsView、QGraphicsScene、QGraphicsItem、Qt GUI

QGraphicsView、QGraphicsScene、QGraphicsItem 和 Qt GUI&#xff08;QGuiApplication&#xff09;可以用来构建和管理基于图形的用户界面。 一、它们之间的关系&#xff1a; QGuiApplication 作为应用程序的基础&#xff0c;提供了窗口和事件管理等功能。 QGraphicsView 则…

15- OpenCV:模板匹配(cv::matchTemplate)

目录 1、模板匹配介绍 2、cv::matchTemplate 3、模板匹配的方法&#xff08;算法&#xff09; 4、代码演示 1、模板匹配介绍 模板匹配就是在整个图像区域发现与给定子图像匹配的小块区域。 它可以在一幅图像中寻找与给定模板最相似的部分。 模板匹配的步骤&#xff1a; &a…

中移(苏州)软件技术有限公司面试问题与解答(4)—— virtio所创建的设备2

接前一篇文章&#xff1a;中移&#xff08;苏州&#xff09;软件技术有限公司面试问题与解答&#xff08;4&#xff09;—— virtio所创建的设备1 在上一篇文章中&#xff0c;对于面试所提出的问题“virtio会创建哪些设备&#xff1f;”&#xff0c;有了初步答案&#xff0c;即…

基于python和定向爬虫的商品比价系统实现

目录 前言 一、系统设计 1. 系统需求分析 2. 系统设计思路 二、系统实现 1. 爬虫部分 2. 比价部分 3. 完整系统代码 三、系统优化 1. 多线程爬取 2. 引入数据库 四、总结 前言 商品比价系统是一种可以帮助用户快速找到最优价格商品的系统。本文将介绍如何使用pyth…

开源的API Gateway项目- Kong基于OpenResty(Nginx + Lua模块)

Kong 是一个在 Nginx 内运行的开源 API 网关和微服务抽象层。它是用于处理 API 流量的灵活、可扩展、可插入的工具。 Kong 提供了以下功能&#xff1a; 用户登录&#xff1a;Kong 提供了多种认证插件&#xff0c;像 JWT、OAuth 2.0 等&#xff0c;可以满足用户登录需求。Toke…

Linux---文件系统

在基础IO中&#xff0c;我们所讲的都是对被打开文件的管理&#xff0c;但是不是所有的文件都是被打开的&#xff0c;对那些在磁盘中保存的没有被打开的文件&#xff0c;我们同样也需要管理&#xff0c;这个就像是快递站中等待被人取走的快递&#xff0c;我们需要将它们分门别类…

Java项目:15 springboot vue的智慧养老手表管理系统

作者主页&#xff1a;源码空间codegym 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 本系统共分为两个角色&#xff1a;家长&#xff0c;养老院管理员 框架&#xff1a;springboot、mybatis、vue 数据库&#xff1a;mysql 5.7&…

Fink CDC 1.0 至3.0的从古至今

本文主要分享Flink CDC 1.0 至3.0的发展历程,了解其背后的关键特性和发展趋势,探讨其在大数据领域的影响和价值。 一、CDC概述 CDC是一种用以掌控数据变化的软件架构(技术思路),用于捕获和传递数据库中发生的数据变化。当数据库中发生增(INSERT)/删(DELETE)/改(UPD…

#GPU|LLM|AIGC#集成显卡与独立显卡|显卡在深度学习中的选择与LLM GPU推荐

区别 核心区别&#xff1a;显存&#xff0c;也被称作帧缓存。独立显卡拥有独立显存&#xff0c;而集成显卡通常是没有的&#xff0c;需要占用部分主内存来达到缓存的目的 集成显卡&#xff1a; 是集成在主板上的&#xff0c;与主处理器共享系统内存。 一般会在很多轻便薄型的…

win11 C盘出现感叹号

Win11系统中&#xff0c;出现本地磁盘上出现黄色感叹号&#xff0c;是BitLocker未关闭或者正在激活导致 解决方案&#xff1a; 鼠标右键点击开始菜单 &#xff0c;之后选择“Windows终端”管理员 管理-bde状态&#xff1b;# #检查状态 管理-bde&#xff1f;# #查看帮助 Mana…