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

推荐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与Final5.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 Shape1Rectangle r1(1.0,2.0,"Rectangle1");r1.draw();// Rectangle Drawing Rectangle1 with x: 1,y: 2Square sq1(3.0,"Square1");sq1.draw();// Square Drawing Square1 with x: 3// Base PointerShape* shape_ptr = &s1;shape_ptr->draw();// Shape Drawing Shape1shape_ptr = &r1;shape_ptr->draw();// Shape Drawing Rectangle1shape_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 PointersShape* 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");// Pointercout<<"*********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.mzph.cn/news/648285.shtml

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

相关文章

git常见命令

1、常用命令记录 1&#xff09;切换分支 git checkout 分支名2&#xff09;查看分支 查看远程分支 git branch -r 查看所有分支包括本地分支和远程分支 git branch -a3&#xff09;合并分支 git merge 来源分支4&#xff09;删除分支 删除本地分支&#xff1a;git branch …

让B端管理软件既美观又实用的解决方案来了

hello宝子们...我们是艾斯视觉擅长ui设计和前端开发10年经验&#xff01;希望我的分享能帮助到您&#xff01;如需帮助可以评论关注私信我们一起探讨&#xff01;致敬感谢感恩&#xff01; 让B端管理软件既美观又实用的解决方案来了 在当今数字化时代&#xff0c;B端管理软件已…

解密神经网络:深入探究传播机制与学习过程

解密神经网络&#xff1a;深入探究传播机制与学习过程 文章目录 解密神经网络&#xff1a;深入探究传播机制与学习过程一、引言二、基础理论1. 人工神经元&#xff1a;构建块的定义2. 神经网络的结构3. 激活函数的作用 三、前向传播1. 数据流动&#xff1a;输入到输出2. 加权和…

安泰ATA-4014高压功率放大器在超声马达驱动电路设计中的应用

本文将与大家分享&#xff0c;ATA-4014高压功率放大器在超声马达驱动电路设计和制作中的应用&#xff0c;希望能对各位工程师有所帮助与启发。 1引言 超声波马达又称超声电机(ultrasonicmotor&#xff0c;简称USM)20世纪80年代才诞生的一种全新概念电机种类.超声电机采用与传统…

Linux之buildroot

Buildroot 是用于生成嵌入式Linux系统的完整构建工具链和环境。 Buildroot 通过自动化编译过程&#xff0c;可以帮助你从零开始构建一个自定义的、优化的嵌入式Linux系统&#xff0c;该系统通常包括以下几个关键部分&#xff1a; 交叉编译工具链&#xff1a;Buildroot会自动构建…

网络端口与 IP 地址有什么区别?

网络端口和IP地址是计算机网络中两个非常重要的概念&#xff0c;它们在实现网络通信和数据传输中扮演着不同的角色。 IP地址 IP地址&#xff08;Internet Protocol Address&#xff09;是用于标识网络上设备的唯一地址。它是一个由数字组成的标识符&#xff0c;用于在网络中准…

华为AC+FIT AP组网配置

AC配置 vlan batch 100 to 101dhcp enableip pool apgateway-list 192.168.100.254 network 192.168.100.0 mask 255.255.255.0 interface Vlanif100ip address 192.168.100.254 255.255.255.0dhcp select globalinterface GigabitEthernet0/0/1port link-type trunkport trun…

马尔可夫预测(Python)

马尔科夫链&#xff08;Markov Chains&#xff09; 从一个例子入手&#xff1a;假设某餐厅有A&#xff0c;B&#xff0c;C三种套餐供应&#xff0c;每天只会是这三种中的一种&#xff0c;而具体是哪一种&#xff0c;仅取决于昨天供应的哪一种&#xff0c;换言之&#…

2024年会是大牛市吗?我有500万想找个证券公司开融资融券账户,哪家券商两融利率最低?

2024年是否会迎来大牛市&#xff0c;这是一个颇具争议的话题。然而&#xff0c;无论市场走势如何&#xff0c;对于有500万的投资者来说&#xff0c;开立一个融资融券账户确实是一个不错的选择。在选择券商时&#xff0c;除了考虑两融利率外&#xff0c;投资者还应该关注券商的服…

10. UE5 RPG使用GameEffect创建血瓶修改角色属性

前面我们通过代码实现了UI显示角色的血量和蓝量&#xff0c;并实现了初始化和在数值变动时实时更新。为了测试方便&#xff0c;没有使用GameEffect去修改角色的属性&#xff0c;而是通过代码直接修改的数值。 对于GameEffect的基础&#xff0c;这里不再讲解&#xff0c;如果需要…

5.列表选择弹窗(BottomListPopup)

愿你出走半生,归来仍是少年&#xff01; 环境&#xff1a;.NET 7、MAUI 从底部弹出的列表选择弹窗。 1.布局 <?xml version"1.0" encoding"utf-8" ?> <toolkit:Popup xmlns"http://schemas.microsoft.com/dotnet/2021/maui"xmlns…

幻兽帕鲁游戏多人联机服务器价格对比:腾讯云VS阿里云VS华为云

《幻兽帕鲁》游戏5天捞金15亿&#xff0c;而且想要多人联机玩游戏&#xff0c;还允许我们自己购买服务器来搭建专属服务器&#xff0c;届时三五好友一起来玩&#xff0c;真的不要太爽啊&#xff01;那么搭建幻兽帕鲁游戏多人联机的服务器需要多少钱&#xff1f;下面boke112百科…

软件产品著作权证书需要哪些资料

1、软件源程序代码(前、后各连续30页&#xff0c;共60页&#xff1b;不足60页全部提交) 2、软件用户手册、操作手册、设计说明书、使用说明书等任选一种 3、身份证明 A著作权人为个人 应提交身份证复印件一份&#xff0c;如有工作单位&#xff0c;可以要单位出具非职务软件开…

在 Ubuntu 18.04 x86_64 上面安装 Linux-ARMv7 A/L GCC编译器

一键安装 Linux-ARMv7A GCC编译器&#xff1a;&#xff08;平板、手机一般是&#xff09; ########################### 输入以下命令&#xff1a; 1、sudo apt update 2、sudo apt install gcc-arm-linux-gnueabi sudo apt install g-arm-linux-gnueabi 3、arm-linux-gn…

Vue3 Element-plust表格导出excel文件

安装插件&#xff1a; npm i js-table2excel 引入插件&#xff1a; import table2excel from "js-table2excel"; table收集数据&#xff1a; <el-tablesize"small"ref"multipleTableRef":header-cell-style"{ background: #f5f6fa, co…

搜索引擎Elasticsearch了解

1.Lucene 是什么? 2.模块介绍 Lucene是什么: 一种高性能,可伸缩的信息搜索(IR)库 在2000年开源,最初由鼎鼎大名的Doug Cutting开发 是基于Java实现的高性能的开源项目 Lucene采用了基于倒排表的设计原理,可以非常高效地实现文本查找,在底层采用了分段的存储模式,使它在读…

【JaveWeb教程】(28)SpringBootWeb案例之《智能学习辅助系统》的详细实现步骤与代码示例(1)

目录 SpringBootWeb案例011. 准备工作1.1 需求&环境搭建1.1.1 需求说明1.1.2 环境搭建 1.2 开发规范 2. 部门管理 SpringBootWeb案例01 前面我们已经讲解了Web前端开发的基础知识&#xff0c;也讲解了Web后端开发的基础(HTTP协议、请求响应)&#xff0c;并且也讲解了数据库…

偏差,均方根误差RMSE

目录 一、均方误差MSE​编辑 二、R自定义函数 三、均方根误差(RMSE), 平均绝对误差(MAE), 标准差(Standard Deviation)的对比 参考&#xff1a; 一、均方误差MSE 这里使用trace是因为多元情形下方差是矩阵。 二、R自定义函数 来自&#xff1a;2022 - Biometrical Journal - …

electron-builder vue 打包后element-ui字体图标不显示问题

当使用electron打包完成的时候&#xff0c;启动项目发现使用的element-ui字体图标没显示都变成了小方块&#xff0c;并出现报错&#xff0c;请看下图&#xff1a; 解放方法&#xff1a; 在vue.config.js中设置 customFileProtocol字段&#xff1a;pluginOptions: {electronBui…

数组里对象排序

let arr [{age:20,name:张三‘},{age:21,name:里斯‘},{age:22,name:王武‘}, ]arr.sort(function (a, b) {return a.age - b.age; // 按照升序排列 });