【C++知识点总结全系列 (08)】:面向对象编程OOP

这里写目录标题

  • 1、OOP概述
    • (1)面向对象四大特征
      • A.抽象
      • B.封装
      • C.继承
      • D.多态
    • (2)构造函数
      • A.What(什么是构造函数)
      • B.Why(构造函数的作用)
      • C. Which(有哪些构造函数)
    • (3)析构函数
      • A.What(什么是析构函数)
      • B.Why(析构函数的作用)
    • (4) =default 和 =delete
      • A.Why
      • B.How
  • 2、继承
    • (1)What(什么是继承)
    • (2)Why(继承的作用)
    • (3)How(如何使用继承)
    • (4)虚函数
      • A.What
      • B.Why(虚函数的作用)
      • C.使用虚函数的注意事项
    • (5)虚析构函数
      • A.Why(虚析构函数的作用)
      • B.What(什么是虚析构函数)
    • (6)抽象基类
      • A.What(纯虚函数&抽象基类)
      • B.抽象基类的特点
    • (7)继承关系中的访问控制
      • A.类中成员的访问权限
      • B.类继承中的访问权限
      • C.派生类向基类转换的权限问题(向上转型)
      • D.友元在继承中的访问权限
    • (8)多重继承
      • A.横向多重继承:
      • B.纵向多重继承:
      • C.联合多重继承:
    • (9)虚继承
      • A.What(什么是虚继承、虚基类)
      • B.Why(虚继承的作用)
      • C.How
  • 3、多态(编译时多态)-重载
    • (1)输入输出运算符重载
    • (2)算术运算符:+、-、*、/
    • (3)关系运算符:>、>=、==、<=、!=
    • (4)赋值运算符
    • (5)下标运算符
    • (6)递增递减运算符
    • (7)解引用运算符和箭头运算符
    • (8)重载new和delete
      • A.Why(为什么要重载new和delete运算符)
      • B.How(如何重载)
    • (9)函数调用运算符
      • A.什么是函数对象
      • B.函数对象lamda

1、OOP概述

(1)面向对象四大特征

A.抽象

把一类东西的共同属性和方法提取到一个类中,而不关注具体如何实现

B.封装

对象属性对外接是隐藏的,只能通过对象的方法进行访问和修改

通过类实现对现实情况的抽象,使用private权限实现对类的封装

class Caculater{ 
private:int *Id; // 对数据进行封装,只有类能访问,外部智能通过提供的函数访问 
public:Caculater() { // 默认构造函数std::srand(std::time(nullptr)); int randomNumber = std::rand(); Id = new int;*Id = randomNumber; }Caculater(Caculater &caculater) { // 拷贝构造函数Id = caculater.getId();}~Caculater() { delete Id; } void showId(){if(Id) cout << "Id = " << *Id << endl; else cout << "nullptr" << endl;}template <class T, class U> auto add(const T &t, const U &u) const {return t + u; }int *getId() {return Id; }
};
template <typename T> 
void printf(const T &&t) { cout << t << endl; } 
int main(){// 隐式调用默认构造函数 Caculater caculater01; // 调用成员函数printf(caculater01.add(20, 10.1)); // 打印:30.1return 1;
}

C.继承

派生类可以继承基类的非私有属性和方法,而无需自己重新定义

D.多态

静态多态:编译时多态

函数重载或模板重载

动态多态:运行时多态

父类型可以指向其子类型的实例,使子类型对同一方法作出不同的回应,也就是所谓的动态绑定

动态绑定

通过基类指针或引用调用虚函数时,会根据实际对象的类型来确定要调用的函数版本 基类的引用或指针调用虚函数 virtual 时发生动态绑定

(2)构造函数

A.What(什么是构造函数)

一种特殊的成员函数:
一方面它没有返回值
另一方面它和类名相同

B.Why(构造函数的作用)

主要作用是创建初始化类对象:为对象的成员赋初始值、执行一些必要的初始化操作等

C. Which(有哪些构造函数)

无参构造函数

如果没有显式定义任何构造函数,编译器将自动生成一个默认构造函数(合成默认构 造函数)。它不带任何参数,并对类的成员进行默认初始化

带参构造函数

参数列表不为空的构造函数

Student(string strStuName, int iAge )
{	m_strStuName = strStuName;m_iAge = iAge;
}
Student(string strStuName, int iAge = 24)
{m_strStuName = strStuName;m_iAge = iAge;
}

拷贝构造函数

将参数中的对象深拷贝给当前对象,如果存在指针数据,一定要重新开辟空间,然后赋值

Student(const Student &stuObj)
{	this->strStuName = stuObj.getName();this->iAge = stuObj.getAge();this->ptrScore = new float(strObj.getScore());
}

移动构造函数

实现了数据的转移,相当于“鸠占鹊巢,还得把鹊赶尽杀绝”,移动赋值运算符同理

Student( Student &stuObj)
{this->strStuName = stuObj.getName();stuObj.setName("");this->iAge = stuObj.getAge();stuObj.setAge(0);this->ptrScore = new float(strObj.getScore());stuObj.score = nullptr;
}

转换构造函数

本质是带一个参数的构造函数,在需要时可以将其他类型的对象隐式转换为当前类的对象

(3)析构函数

A.What(什么是析构函数)

一个特殊的成员函数:
一方面,对象被销毁时自动调用,它不能是delete的
另一方面,和构造函数一样没有返回值

~Student(){delete this->ptrScore;ptrScore = nullptr;
}

B.Why(析构函数的作用)

  • 可用于释放动态分配的内存
  • 可用于关闭文件、数据库连接和网络连接资源
  • 解锁互斥量或释放其它同步资源

(4) =default 和 =delete

A.Why

更精确地控制类的成员函数的行为,提高代码的可读性和安全性

B.How

class MyClass { 
public:// 默认构造函数 MyClass() = default; // 默认析构函数~MyClass() = default; // 禁用拷贝构造函数MyClass(const MyClass&) = delete; // 禁用赋值运算符MyClass& operator=(const MyClass&) = delete; // 禁用移动构造函数MyClass(MyClass&&) = delete; // 使用默认移动赋值运算符MyClass& operator=(MyClass&&) = default;
};

2、继承

(1)What(什么是继承)

派生类从基类继承属性和方法

(2)Why(继承的作用)

重用性:派生类可以继承基类的属性和方法,减少重复代码的编写
扩展性:派生类可以在继承基类的基础上添加新的属性和方法,实现更强大的功能
多态性:实现对不同派生类的统一处理

说明:派生类的属性和基类重名时,会自动隐藏基类的成员

(3)How(如何使用继承)

class Derived: public Base{...}

(4)虚函数

A.What

一种特殊的成员函数,在基类中声明并用于被派生类重写的特殊成员函数

B.Why(虚函数的作用)

允许在运行时根据对象的实际类型来调用相应的函数实现,以实现多态性

C.使用虚函数的注意事项

  • override 关键字的使用:只有虚函数才能用 override 修饰(在派生类中使用该关键字)
  • 虚函数与默认实参:如果虚函数使用了默认实参, 则基类和派生类中定义的默认 实参应该一致,基类和派生类的虚函数必须接受相同的形参列表,否则无法实现动 态绑定
  • 回避虚函数机制:通常情况下,只有在成员函数(或友元)中使用作用域运算符来回避虚函数机制
    在这里插入图片描述

(5)虚析构函数

A.Why(虚析构函数的作用)

当我们使用基类指针或引用指向派生类对象,并且在基类指针或引用上删除该对象时, 如果基类的析构函数不是虚函数,则只会调用基类的析构函数,而不会调用派生类的 析构函数。这可能导致资源泄漏和未定义行为

B.What(什么是虚析构函数)

virtual ~Base();

在这里插入图片描述

注意:虚析构函数将阻止合成的移动构造函数和合成的移动赋值运算符,因为默认只 进行浅拷贝,而动态内存分配下的浅拷贝可能导致内存泄漏、悬挂指针等问题

(6)抽象基类

A.What(纯虚函数&抽象基类)

纯虚函数:
在这里插入图片描述
抽象基类:

含有纯虚函数的类叫做抽象基类

B.抽象基类的特点

  • 至少包含一个纯虚函数
  • 不能实例化对象,只能用作其他类的基类
  • 继承抽象基类的派生类必须实现纯虚函数,否则派生类也会称为抽象基类
  • 抽象基类可以包含非纯虚函数,提供默认或共享的功能

(7)继承关系中的访问控制

A.类中成员的访问权限

  • public:类的对象(外部)可以访问,派生类也可以访问
  • protected:类的对象(外部)不能访问,派生类可以访问
  • private:类的对象(外部)不能访问,派生类也不可以访问

B.类继承中的访问权限

  • public继承:public->public, protected->protected

    派生类可以继承基类中的公有成员和受保护成员,并将其作为自己的公有成员和受保护成员

  • protected继承:public&protected->protected

    将基类中的公有成员和受保护成员作为派生类的受保护成员

  • private继承:public&protected->private

    将基类中的公有成员和受保护成员作为派生类的私有成员,使得派生类无法直接访问这些成员

C.派生类向基类转换的权限问题(向上转型)

在这里插入图片描述
在这里插入图片描述
注意:派生类的成员函数和友元函数中,可以进行向上转型

D.友元在继承中的访问权限

  • 友元不能被继承:友元函数和友元类类似于基类的私有成员
  • 派生类的友元不可直接访问基类成员(包括公有成员)
    在这里插入图片描述在这里插入图片描述

(8)多重继承

A.横向多重继承:

在这里插入图片描述

B.纵向多重继承:

在这里插入图片描述

C.联合多重继承:

在这里插入图片描述

因为 single 和 waiter 都继承了一个 worker 组件,因此 SingingWaiter 将包含两个 worker 组件,那么将派生类对象的地址赋给基类指针将出现二义性

那么如何解决二义性问题呢?我们知道程序的执行一定是具有确定性的,在上述情况下,我们能想到的是进行强制转换,如下所示:
在这里插入图片描述
很显然,上述这种强制转换确实能够解决因联合继承带来的二义性问题,但是每次都进行这样的强制转换过于繁琐,那么有没有简单的办法解决二义性问题呢?答案就是:虚继承,所谓的虚继承,就是让共享一个祖父类

(9)虚继承

A.What(什么是虚继承、虚基类)

  • 虚继承:

class Derived: public virtual Base, 如下例所示,展示了虚继承的形式

在这里插入图片描述

  • 虚基类

被声明为虚继承的基类被称为虚基类

B.Why(虚继承的作用)

  • 解决二义性冲突:当基类的指针指向孙子类的指针或引用时,会出现二义性,因为 孙子类对象包含多个祖父类对象,而虚继承只保留一个共享的祖父类
  • 减少内存消耗:因为孙子类只包含一个祖父类对象
  • 减少代码冗余:虚基类的成员只需在最终的派生类中定义一次

C.How

在这里插入图片描述

3、多态(编译时多态)-重载

(1)输入输出运算符重载

以友元的形式进行重载:

在这里插入图片描述

(2)算术运算符:+、-、*、/

以友元的形式重载:

在这里插入图片描述

(3)关系运算符:>、>=、==、<=、!=

以友元的形式重载:

在这里插入图片描述

(4)赋值运算符

在这里插入图片描述

(5)下标运算符

在这里插入图片描述

(6)递增递减运算符

前置版本:
在这里插入图片描述
后缀版本:
在这里插入图片描述

注意:显式调用后置版本(默认调用前置版本)

在这里插入图片描述

(7)解引用运算符和箭头运算符

箭头运算符和解引用运算符必须是类的成员函数

在这里插入图片描述

(8)重载new和delete

A.Why(为什么要重载new和delete运算符)

重载 new 运算符和 delete 运算符是为了对内存分配和释放过程进行自定义操作,以 满足特定的需求。通过重载这些运算符,我们可以提供自定义的内存管理方法,例如 使用自定义的内存池,跟踪内存分配和释放情况,或进行性能优化

B.How(如何重载)

在这里插入图片描述
在这里插入图片描述

(9)函数调用运算符

函数调用运算符必须是成员函数

A.什么是函数对象

如果类定义了调用运算符,则该类的对象称为函数对象

在这里插入图片描述

B.函数对象lamda

在这里插入图片描述

lamda的引用捕获:

在这里插入图片描述

注意:使用[&]可以引用捕获作用域内所有变量

lambda的值捕获:

在这里插入图片描述

注意:使用[=]可以值捕获作用域内所有变量

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

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

相关文章

【JS|第21期】JavaScript模块化:深入解析三种文件暴露方式

日期:2024年7月6日 作者:Commas 签名:(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释:如果您觉得有所帮助,帮忙点个赞,也可以关注我,我们一起成长;如果有不对的地方,还望各位大佬不吝赐教,谢谢^ - ^ 1.01365 = 37.7834;0.99365 = 0.0255 1.02365 = 1377.4083…

全志A527 T527 android13支持usb摄像头

1.前言 我们发现usb摄像头在A527 android13上面并不能正常使用,需要支持相关的摄像头。 2.系统节点查看 我们查看系统是否有相关的节点生成,发现/dev/video相关的节点已经生成了。并没有问题,拔插正常。 3.这里我们需要查看系统层是否支持相关的相机, 我们使用命令进行…

【INTEL(ALTERA)】为什么我使用 PIO 边缘捕获中断的 Nios® II 设计不能正常工作?

目录 说明 解决方法 说明 当用户选择了不正确的边缘捕获设置&#xff0c;从而阻止触发中断时&#xff0c;可能会出现此问题。 在 PIO&#xff08;并行 I/O&#xff09;英特尔 FPGA IP内核中&#xff0c;如果“启用单个位设置/清除”选项被关闭&#xff0c;则将任何值写入边…

vue实例和容器的一夫一制——04

//准备容器 <div classapp> <h1>{{mag}}</h1> </div> //准备容器 <div classapp> <h1>{{mag}}</h1> </div> //准备容器 <div classapp2> <h1>{{name}}</h1> </div> <script> // 验…

基于Java+SpringMvc+Vue技术的药品进销存仓库管理系统设计与实现系统(论文7000字参考+源码+LW+部署讲解)

博主介绍&#xff1a;硕士研究生&#xff0c;专注于信息化技术领域开发与管理&#xff0c;会使用java、标准c/c等开发语言&#xff0c;以及毕业项目实战✌ 从事基于java BS架构、CS架构、c/c 编程工作近16年&#xff0c;拥有近12年的管理工作经验&#xff0c;拥有较丰富的技术架…

Java虚拟机面试题汇总

目录 1. JVM的主要组成部分及其作用&#xff1f; 1.1 运行时数据区划分&#xff1f; 1.2 哪些区域可能会发生OOM&#xff1f; 1.3 堆和栈的区别&#xff1f; 1.4 内存模型中的happen-before是什么&#xff1f; 2. HotSpot虚拟机对象创建流程&#xff1f; 2.1 类加载过程…

7.9总结

容易推出当移动i与j时等价于j-i-1个左右交换&#xff0c;且每次交换逆序数的奇偶改变&#xff08;无相同元素&#xff09;&#xff0c;假设有一个状态c&#xff0c;且a与b必须以等量的左右交换转移为c&#xff0c;则必须数量相同&#xff0c;元素相同&#xff08;使用异或解决&…

tomcat 项目迁移,无法将项目作为服务service启动

背景 测试服务器需要迁移到正式服务器上&#xff0c;为了方便省事&#xff0c;将测试服务器上的一些文件直接复制到正式服务器 问题 使用startup启动项目之后&#xff0c;可以直接使用使用tomcat9w启动&#xff0c;或者作为服务service启动的时候&#xff0c;显示无法访问到资源…

欧拉部署nginx

1.下载nginx 下载地址&#xff1a;https://nginx.org/en/download.html 选择稳定版本 下的镜像文件进行下载 2.解压Nginx包 cd /root/nginx tar -zxvf nginx-1.26.0.tar.gz cd nginx-1.26.03.安装nginx相关依赖 yum -y install gcc zlib zlib-devel pcre-devel openssl o…

机场公厕厕位指引屏,布线简单,安装便捷

在人潮涌动的机场&#xff0c;公厕不仅是旅客的必需设施&#xff0c;更是衡量机场服务质量的重要指标。然而&#xff0c;传统机场公厕往往存在信息不透明、清洁维护滞后、高峰期拥挤等问题&#xff0c;严重影响了旅客的使用体验。近年来&#xff0c;随着智慧机场理念的兴起&…

Linux 网络--TCP协议收包流程(NAPI机制)

Linux 网络--TCP协议收包流程&#xff08;NAPI机制&#xff09; 平台环境简介&#xff1a;宿主机: ubuntu18.04Linux内核源码版本: Linux-4.15网卡驱动: Intel e1000 &#xff08;ubuntu 虚拟机默认网卡驱动&#xff09;协议&#xff1a;TCP协议&#xff0c;本文分析收包过程 本…

python3 ftplib乱码怎么解决

其实很简单。ftplib.FTP里面有个参数叫encoding。 如上图最后一行。所以在使用FTP时&#xff0c;主动指定编码格式即可。 ftp ftplib.FTP() ftp.encoding "utf-8" 再使用就可以了。

计算机视觉研究院 | 智慧工地:2PCNet,昼夜无监督域自适应目标检测(附原代码)

本文来源公众号“计算机视觉研究院”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;智慧工地&#xff1a;2PCNet&#xff0c;昼夜无监督域自适应目标检测&#xff08;附原代码&#xff09; 由于缺乏夜间图像注释&#xff0c;夜间…

【优先级队列PriorityQueue】

目录 1&#xff0c;优先级队列 1.1 概念 2&#xff0c;优先级队列的模拟实现 2.1 堆的概念 2.2 堆的存储方式 2.3 堆的创建 2.3.1 堆的向下调整&#xff08;大根堆&#xff09; 2.3.2 建堆的时间复杂度​编辑 2.4 堆的插入与删除 2.4.1 堆的插入 2.4.2 堆的删除 3&a…

Github Actions 构建Vue3 + Vite项目

本篇文章以自己创建的项目为例&#xff0c;用Github Actions构建。 Github地址&#xff1a;https://github.com/ling08140814/myCarousel 访问地址&#xff1a;https://ling08140814.github.io/myCarousel/ 具体步骤&#xff1a; 1、创建一个Vue3的项目&#xff0c;并完成代…

Sentinel-1 Level 1数据处理的详细算法定义(二)

《Sentinel-1 Level 1数据处理的详细算法定义》文档定义和描述了Sentinel-1实现的Level 1处理算法和方程&#xff0c;以便生成Level 1产品。这些算法适用于Sentinel-1的Stripmap、Interferometric Wide-swath (IW)、Extra-wide-swath (EW)和Wave模式。 今天介绍的内容如下&…

澳大利亚TikTok直播为什么需要海外直播专线?

近年来&#xff0c;许多卖家为了解决澳大利亚TikTok直播中的卡顿和高延迟问题&#xff0c;纷纷选择使用海外直播专线。这种专线服务是一种高效、低延迟的数据传输解决方案&#xff0c;专为需要高质量网络连接的场合设计。 与公共互联网相比&#xff0c;海外直播专线提供更稳定、…

基于深度学习的电影推荐系统

1 项目介绍 1.1 研究目的和意义 在电子商务日益繁荣的今天&#xff0c;精准预测商品销售数据成为商家提升运营效率、优化库存管理以及制定营销策略的关键。为此&#xff0c;开发了一个基于深度学习的商品销售数据预测系统&#xff0c;该系统利用Python编程语言与Django框架&a…

ubuntu使用kubeadm搭建k8s集群

一、卸载k8s kubeadm reset -f modprobe -r ipip lsmod rm -rf ~/.kube/ rm -rf /etc/kubernetes/ rm -rf /etc/systemd/system/kubelet.service.d rm -rf /etc/systemd/system/kubelet.service rm -rf /usr/bin/kube* rm -rf /etc/cni rm -rf /opt/cni rm -rf /var/lib/etcd …

兼容性报错--调整字符集解决

文章目录 错误解决办法Unicode 字符集(两个字节来表示一个字符)多字节字符集(一个字节来表示一个字符)如何选择字符集char与wchar_t的区别LPCSTR与LPCWSTR的区别 错误 解决办法 切换字符集类型 Unicode 字符集(两个字节来表示一个字符) 优点&#xff1a; 支持更多的字符集…