C++学习笔记(面向对象部分开始6500字复习总结)

news2025/1/4 20:03:56

函数重载

1.对象属性 对象方法 和 类属性 类方法

2.const函数read only,不会修改任何数据

3.class默认private,struct默认public

4.!!!!C++编译器优化!!!《个人理解》当需要调用拷贝构造时,就一直往前传递this地址指针,省掉中间的拷贝构造,直接让对应接口的构造函数在目标对象的地址上进行构造

5.函数重载的原理是根据目标文件进行区分,参数列表不同,目标文件中的函数名也会不同

6.函数重载时的冲突

有默认值的函数会涵盖无默认值但其余参数相同的函数,比如:func(int a, 7) 可以接收单个int参数,也能接收两个参数,此处就与func(int a)冲突了

底层const是一类,顶层const和非const是一类,同类会冲突,所以顶层const和非const不能进行重载

运算符重载与仿函数

1.默认函数的说明与禁用

/*此处仅仅做说明,表明编码者的意图,但并不会禁用默认的构造函数等等

如要禁用,将其放入private即可,运算符等类成员都可*/

2.friend类内声明,声明对象类外即可对类访问

3.委托构造?可以委托其他构造函数的结构给自己构造↓↓↓↓↓↓↓↓↓↓↓↓

4.输出不便时,重载<<运算符,例如:输出数组

 5.调用函数接口只需要函数名即可,函数传参时可以传右值,比如类的匿名函数,CMP()拷贝构造一个匿名函数

6.仿函数比起函数,可以应用类的功能,比如重载运算符,构造传参等等

 7.↑↑↑↑↑↑↑↑异或运算符的应用,传参0 ^ 判断1,即为1,此时逻辑为判断为真即为真,为假即为假,传参1 ^ 判断1,此时逻辑判断为真即为假,假即为真,与判断相反,即实现传参决定判断顺逆

sort封装

1.基于快排,利用function<bool(int, int)> cmp,可以指向函数与仿函数、lambda表达式

2.↓↓↓↓↓↓↓↓ 1.函数传参默认实参:默认排序方式 2.函数传参决定排序方式

 3.继承权限:class 类名 :继承权限 继承父类 {};例:class Cat :public animal {}

; public、protected、private权限依次提高

外部可访问、可被继承、不可访问不可继承 三层权限

父子类权限相交时,有高级权限则取高级权限,例如父类protected、子类public,则权限为protected,以此类推

4.继承时数据成员拷贝,方法可访问

5.智能指针

当指针置空时,会自动释放申请的动态内存

use_count()能统计指向同一地址的有几个指针

继承与虚函数

1.继承时的方法调用:子类调用自身方法之前,必须先调用父类的方法,例如:子类调用拷贝构造,父类必须先调用拷贝构造,运算符同理

2.↓↓↓↓↓↓↓子类构造函数参数列表(必须)调用父类构造函数传参

 

子类运算符重载也要调用父类运算符重载(当成函数来用,同样是继承的方法)

3.多继承

语法

 多继承时继承顺序由继承列表顺序决定

多继承时会产生菱形继承◇

4.继承的运用,作为功能类,利用继承的特性,使继承的子类有了父类的属性

因为继承父类会继承方法的调用,如果父类是不可拷贝的属性,那么子类也将无法拷贝

 5.虚函数的使用与原理,

虚函数将只会被作为对象成员调用,而不是被作为类方法调用,因为普通函数是在编译阶段就已经用被编译器确认调用哪一个函数,而虚函数在编译阶段调用的只是一个函数指针,而运行阶段才会决定该指针指向哪里

6.override和final是虚函数重写时的说明:

override可以做说明,也可以提醒有对应的虚函数,如果没有,编译器会报错

 final做说明,当前是最后一次重写该虚函数,后面不可再对该虚函数重写,起限制作用

7.用virtual修饰的函数将不会被作为类型的方法调用,比如类A有个指针p指向的是对象B,此时对p进行调用函数,会调用类A的函数,而不是对象B的函数,这显然不是我们想达到的,虚函数就可以在这里防止被同名误调

 8.虚表vtable里存放了可能指向的函数指针

编译阶段将重写的函数入口放入vtable里,调用虚函数时,调用的其实是一个函数指针,运行的时候才能确定该指针指向vtable中的哪个函数接口

9.变量的最小单位为1,意义是说变量至少得有一块内存空间,所以分配了最小的一块内存,实际上数据大小为0

10.函数变成虚函数,类方法变成对象方法,对象方法就是说该方法确实存在一个变量里面,就应该有它自己的内存大小,比如虚函数就需要储存它的函数入口地址

11.虚函数总结

有虚函数时会将虚函数表的首地址写入类中,占据8个字节,类似于一个隐形的数据成员

读取一个类型的虚函数表需要将类的类型转换为指针类型,此处感悟,程序中数据的运算形式(即运算符的操作形式)是由该变量的类型决定,int也可以看做一个变量,它是定义int类的那一块空间的地址,将int转换为void *,就可以访问int类定义的地址了,类比自定义的类结构,访问类定义的地址后,前8个字节就是虚函数表的首地址,再对首地址进行遍历函数接口,就可以输出所有的函数了

继承时,虚函数表会像数据成员一样被拷贝到子类中,子类中有同名函数时,便会用子类中的函数接口覆盖虚函数表中的函数接口,也就是重写,然后其他函数的接口也会加入虚函数表中,所有继承类共用同一个虚函数表

封装基准测试工具

1.类成员指针

类成员可以被指针记住,但该指针必须在该类的作用域下,对象访问该指针也就是访问该指针记住的成员了,这样就实现了在类定义外用指针记住类的成员

 2.C++强制类型转换的必要性

如果使用(type)小括号进行类型转换,当类型转换出错时,很难定位,但使用static_cast<type>

进行类型转换,类型转换出问题时,直接搜索static_cast即可查找 

3.dynamic_cast

父类到子类的类型转换,需要父类有虚函数生成的虚函数表

虚函数表中函数入口数组的头指针的前面还有两个指针,第二个指针存放了类型结构的typeinfo,也叫rtti(run time type information),

typeinfo里面存放了类型的名称,继承的父类,虚表的信息等

从汇编角度讲,dynamic进行类型转换时,是调用了双方类型的typeinfo来对比转换

在使用vrtual虚函数时,-fno-rtti 该命令后缀可以关闭rtti的生成,因为rtti是dynamic_cast使用时必须进行调用,所以不使用dynamic的时候可以关闭rtti,可以节约空间,而使用dynamic_cast也就意味着会耗费更多的时间和空间

 如果不使用vrtual虚函数,那么上面汇编码中的vtable虚函数表也不会生成

4.虚析构的必要性

父类指针指向子类对象时,delete父类指针时,只会调用父类自己的析构函数,而不会调用子类对象的析构函数,因为此时只能调用该对象的类方法,然而将析构函数写为虚函数,就可以在delete对象时,先调用对象本身的析构函数,再调用父类的析构函数

5.抽象类与纯虚函数

纯虚函数:待实现的虚函数,具体实现交给子类去各自重写

抽象类:因为纯虚函数没有定义,没有实例,无法运行,所以抽象类不能被构造,只能被继承

抽象子类:因为子类继承了父类的纯虚函数,如果不进行重写的话,意味着该子类也拥有一个没有定义没有实例的函数,该子类也就无法被构造,该子类也就成为了抽象类,所以抽象类的子类通常都要重写父类的纯虚函数,才能实例化

6.智能指针的应用

当使用的指针不需要多指针同时指向一块内存,但同时又需要智能指针的自我销毁功能,就可以使用效率更高的unique_ptr<type> 对象

关键字

1.auto

总结用法:用来替代一些极长的类型,不可用于形参,数据成员,数组

2. const constexpr

顶层const的变量在汇编层就已经全局替换成了对应的常量

const要求在运行时可读

constexpr要求在编译阶段时可读

 顶层const和constexpr作全局变量时,在编译阶段直接将对应的变量名进行替换为常量,意思是根本没有进行存储,而是直接存在了代码段里,不在栈段堆段data段,而是在text段

在main函数中时,至少会占一块栈内存,此时constexpr在编译阶段进行替换,const在运行阶段替换

3.nullptr

NULL在C语言里可以表示0和(void *),但在C++里引入了函数重载,test(NULL)究竟调用整型参数还是整型指针参数呢,所以引入了nullptr加以区分

4.左值右值及其引用

左值:内存

右值:临时值

左值引用:对左值引用

右值引用以及移动构造:

1.将右值直接转换为左值,在C++里,通常产生了右值以后,必须将右值拷贝到一个左值才能保存,但这个拷贝如果是面对大型容器多次拷贝,会产生大量的资源损耗,而直接将右值转换为左值,则节省这些损耗,此时,将右值转换为左值的操作成为移动构造

2.在函数重载中作为参数匹配右值

右值引用与对const引用的原理:汇编层来看,这两个操作没有区别,对const引用时,就是将变量先进行隐式转换生成同类型的右值,然后把这个匿名的右值对象存入一块内存,变成存在于内存中的左值对象,另外,const会赋予该左值只读权限

一些左右值函数转换方法

move(),将左值转换为右值返回

forward<int &>() ,显式转换为左值

forward<int &&>() ,显式转换为右值

5.三种拷贝构造的特点

class A{}; 

A a;

A  b(a);

浅拷贝(默认拷贝构造):将a的对象全部拷贝到b,b的指针指向的空间和a指向的空间是同一片空间,此时如果进行析构,会对同一片空间析构两次,产生内存泄漏

深拷贝:构造一个新的对象b,申请同样大的内存,构造一个数据和a一样的对象b,如果程序要求对一大型容器进行拷贝构造,进行函数之间返回匿名对象等操作,会产生大量的资源消耗,大量的没有必要的匿名对象被构造和析构

移动构造:基于浅拷贝的基础上,将待析构的对象的所有对象置空,此时a不再和b指向同一片空间,a被析构也不会产生内存泄露,就相当于a把所有数据以及内存移交给了b,而不是像深拷贝一样构造了一份,也就节约了资源的损耗

三种构造的重载:

浅拷贝是默认构造

深拷贝的参数是左值,接住一个对象然后构造一个一样的

移动构造的参数是右值,接住一个临时值,然后在临时值被析构掉之前将它的数据移交给一个新的对象

强行调用移动构造个人理解为对象重命名,将左值显式转换为右值,然后再移交数据给一个新的左值对象

模板

1.模板的本质

定义模板的代码并不进行编译,所以也不占据内存,而是在调用同名模板时,自动生成一个对象或者方法

2.函数模板

调用函数时写入的参数类型决定该函数的定义,这个参数类型可以用<type>显式强调

当函数参数类型不同时,可先将返回值类型后置(便于decltype读取参数类型,如果返回值位于参数前面,参数就还没生成,decltype就读取不到参数的类型),然后使用decltype读取返回值类型

3.模板类和类模板成员

调用模板类时,根据构造对象时给模板写入的类型来构造一个类型定义以及对象

 类模板成员则是,当该模板作为类的成员方法时,调用该类对象的方法时,写入的类型决定该方法的定义,与函数模板类比来讲,就是类的成员函数模板,首先要该类对象才能调用该模板函数,调用的时候写入的类型来决定成员函数的定义

4.引用折叠(奇左偶右)

C++中,单数引用就是左值引用,偶数引用(除了0)都是右值引用

template进行推理类型的时候,如果是引用类型,需要在待推理类型前加上&&,

比如Test(T &&a, T &&b);

此时如果a是右值,T则会推理为非引用类型,比如 int &&a,T是int

a为左值,T推理为引用类型,比如 int &&&a,T是int &,此时参数类型也等于 int &a,

此时就实现了参数类型和推理类型的统一

提问:为什么Test(T &a,T &b)不行

同上推理,如果接收左值,a类型为int &,此时T推理为int,此时类型并不统一,接收右值同理

5.类特化(模板重载)

模板不能推导出指针类型,所以指针类型需要进行特化

template <typename T *>

test(T *a, T *b);

类似于函数重载里的默认实参,但是模板进行匹配时,是优先匹配参数类型定好的模板

模板类用于定义模板,类模板用于对象创建

6.不定参类型

可用于递归参数类型,每次递归传参时,传args,这样第一个变量a,就被使用,递归结束条件为只剩一个参数,此时调用只有一个参数的函数重载

 

 能用于函数,自然也就能用于模板类,模板接收不定参类型,或者类方法接收不定参变量,然后用于递归,仿函数模板也可以接收类型作为形参

递归可以自己写入终止条件,比如在模板类里,进行成员类递归,意思就是不断地调用成员类,终止条件就是自己重载了一个特化模板类,并且里面有一个特化调用成员

有一说一,有点复杂,总是就是玩的很花,会玩怎么都可以,建议自己找代码看

7.模板的用法

模板递归的递归结束点应该是判断条件,模板特化重载时生成不同的数据成员,以此作为判断条件

高级模板

1.类型萃取

给类型加上引用,去掉引用,加上指针,去掉指针

主要是在模板内应用typedef来对类型进行萃取

比如下图,无论写入模板的是什么类型,只需要把对应类型进行typedef成为T & ,就完成了对类型的萃取,萃取的意思也是从写入的参数中,提取需要的部分,再进行加工

2.高级函数指针

如果一个类模板要接收不同的类型来定义不同的模板类,同时还要接收不同的传参,来进行类方法的重载(比如转换构造的重载),

那么首先,因为要接收不同的传参args,所以必须有一个类成员ptr能调用不同的构造函数来对这个传参args进行构造

那么这个类成员ptr,就应该是一个基类base,因为基类才能指向不同的子类的构造函数,以及子类中重写的各种方法

比如,接收的是一个普通函数接口p,那么ptr就重载普通函数的转换构造,并在参数列表里调用普通函数类的构造函数来对p进行构造,然后用p初始化ptr

如果传参是仿函数p,那么ptr就重载仿函数的转换构造,并在参数列表里调用仿函数类的构造函数来对p进行构造,然后用p初始化ptr

对该类模板定义的类构造的对象进行调用时,比如重载运算符()

 

就对ptr调用重写的run()函数,因为此时的ptr是构造好的子类对象,为了避免传参过程中右值引用的左值化,可以调用forward(<变量原type>变量),保证变量类型不变

线程池

公共资源:任务列表,凡是涉及读写,需要抢锁

分为多个部分

1.线程池实现

构造函数:开辟n个线程,绑定线程函数

线程函数:

        功能实现:调用获取任务函数,运行任务 

        生命周期:由自身的线程id绑定一个bool值的键值对,以此通过键值对对bool值进行操作,操控该线程是否运行

任务队列:

        获取任务函数:条件变量等待响应(避免惊群效应),响应后返回并弹出释放任务队列中的任务

关停函数:

        终止任务:函数内容将线程的键值对bool值设为false

        终止线程池函数:加入n个终止任务到任务列表,被线程获取并运行后,线程全部终止,此时join给线程收尸,并delete释放内存

线程池接口:

        加入任务函数:将函数加入任务列表,发出信号,再由线程去抢夺

高级函数指针封装:

        模板写入函数名和参数列表,使用bind(函数名,参数列表),将任意函数封装成一个函数指针,统一将此类函数指针加入任务列表

异常捕捉

try{

        }catch(错误信息){

                }

程序发生错误会抛出错误,如果在try块内,则会对报错进行捕捉,然后跳转到匹配的catch块继续运行程序,没有匹配的catch块就继续往外跳出,跳出到最外层就会被系统捕捉

错误信息可以自定义类,也有定义好的错误类,可查阅资料得知

lambda函数式编程

直接对比代码

面向对象

函数式

[特殊传参(详细查资料)](参数列表)-> 返回值后置(无返回值,或者仅返回语句可不写) { 实现; };

特殊传参内容

​​​​​​​

 

 

 

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

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

相关文章

单细胞分析:数据整合(九)

导读 本文将学习跨条件执行单细胞整合&#xff0c;以识别彼此相似的细胞。 1. 目标 跨条件对齐相同的细胞类型。2. 挑战 对齐相似细胞类型的细胞&#xff0c;这样就不会因为样本、条件、模式或批次之间的差异而在后续分析中进行聚类。 3. 推荐 建议先不整合分析&#xff0c;再决…

2020下半年软件设计师上午题错题总结

2020下半年 1、以下关于两个浮点数相加运算的叙述中&#xff0c;正确的是 &#xff08;3&#xff09; 。 A. 首先进行对阶&#xff0c;阶码大的向阶码小的对齐 B. 首先进行对阶&#xff0c;阶码小的向阶码大的对齐 C. 不需要对阶&#xff0c;直接将尾数相加 D. 不需要对阶…

[附源码]java毕业设计网上购物商城

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

33.nacos客户端读取多配置文件实例(springcloud)

1.配置文件的读取方式【重点】nacos 配置中心通过 namespace、dataId 和 group 来唯一确定一条配置。 Namespace&#xff1a;即命名空间。默认的命名空间为 public&#xff0c;我们可以在 Nacos 控制台中新建命名空间&#xff1b;dataId&#xff1a;即配置文件名称 Group &…

比 O(nlog(n)) 做得更好——创造合适的条件

我们可以比 O(nlog(n)) 更快地排序。 长按关注《Python学研大本营》&#xff0c;加入读者群&#xff0c;分享更多精彩 扫码关注《Python学研大本营》&#xff0c;加入读者群&#xff0c;分享更多精彩 介绍 我将介绍一种我称之为 groupSort 的排序方法。我没有直接解决排序问题…

基于小波变换编码的纹理图像分割

目录 1.算法概述 2.仿真效果预览 3.MATLAB部分代码预览 4.完整MATLAB程序 1.算法概述 我们使用11或13维特征向量表示图像中的每个像素。两个特征用于表示像素之间的空间关系&#xff1b;由图像尺寸规格化的x和y像素坐标。对于灰度图像&#xff0c;一个特征是低通表示&#…

Python编程从入门到实践 第十一章:测试代码 练习答案记录

Python编程从入门到实践 第十一章&#xff1a;测试代码 练习答案记录 练习题导航Python编程从入门到实践 第十一章&#xff1a;测试代码 练习答案记录11.1 测试函数11.1.1 单元测试和测试用例11.1.2 可通过的测试11.1.3 未通过的测试11.1.4 测试未通过时怎么办11.1.5 添加新测试…

Flutter/Dart 中的 extension 方法

Flutter Dart 中的 extension 方法 前言 我们将讨论 extension 方法如何对我们有用&#xff0c;以及为什么您的代码因为它们而变得更加精确和可读的原因。 简介 在本文中&#xff0c;我们将学习 Dart 中的 extension 方法。也许你想知道那是什么&#xff0c;它是如何工作的&…

HIve数仓新零售项目DWS层的构建(Full join)模型

HIve数仓新零售项目 注&#xff1a;大家觉得博客好的话&#xff0c;别忘了点赞收藏呀&#xff0c;本人每周都会更新关于人工智能和大数据相关的内容&#xff0c;内容多为原创&#xff0c;Python Java Scala SQL 代码&#xff0c;CV NLP 推荐系统等&#xff0c;Spark Flink Kaf…

全自动调节灯光强度的实现(仿真+程序+文档)

目 录 摘 要 I Abstract II 绪论 1 1.1 选题背景及意义 1 1.2 国内外研究现状 1 1.3 研究主要内容 3图书馆学习桌台灯智能控制系统简介与方案分析 4 2.1 大学图书馆照明控制现状 4 2.2 图书馆学习桌台灯智能控制系统简介 4 2.3 系统控制方案分析 4 2.4 本章小节 5系统硬件设计…

JavaScript练手小技巧:我破解了原神官网全屏滚动的秘密

这个标题有点夺人眼球&#xff0c;哈啊哈~骗点击率的。 “原神”官网当真的做的很漂亮&#xff0c;虽然我没玩过这个游戏&#xff0c;但是禁不住喜欢这个网站啊。 https://ys.mihoyo.com/ 最近居家教学上网课。除了上课&#xff0c;实在不想做学校安排的其它任务&#xff0c…

热量衡算习题课

第一部分 --- 传热计算综合例题 1.qm是质量流量&#xff0c;T1&#xff0c;2和 t1,2对应的是热流体和冷流体分别在管道进口和出口的温度 2.吊塔tm是传热温差 3.α1是热流体的对流传热系数&#xff0c;α2是冷流体的对流传热系数&#xff0c;K是整个对流传热过程的总的传热系…

【Linux】在Xilinx平台上实现UVC Gadget(2)- 解决dwc3驱动bug

【Linux】在Xilinx平台上实现UVC Gadget&#xff08;2&#xff09;- 解决dwc3驱动bug一、bug描述二、具体修改方法1. 找到内核源码位置并复制到其他目录2. Petalinux里面设置使用自定义内核源码1) 选第2个Linux Components Selection2) 选linux-kernel&#xff0c;回车&#xf…

【笔试题】【day22】

文章目录第一题&#xff08;循环队列的元素个数&#xff09;第二题&#xff08;二叉排序树插入规则&#xff09;第三题&#xff08;线性探测的平均查找长度&#xff09;第四题&#xff08;关键字比较次数与初始序列无关的&#xff09;第一题&#xff08;循环队列的元素个数&…

m短波宽带通信系统的信道建模matlab仿真

目录 1.算法概述 1.1 Watterson信道模型理论简介 1.2 Nakagami信道模型 2.仿真效果预览 3.MATLAB部分代码预览 4.完整MATLAB程序 1.算法概述 宽带短波信道的研究是设计宽带大容量短波通信的基础&#xff0c;但是传统的短波信道的研究仅限于窄带信号传输&#xff0c;这已经…

论文阅读-Whisper语音识别(OpenAI)

一、论文信息 论文名称&#xff1a;Robust Speech Recognition via Large-Scale Weak Supervision 代码地址&#xff1a;https://github.com/openai/whisper 官方博客&#xff1a;https://openai.com/blog/whisper 作者团队&#xff1a;OpenAI 二、介绍 Whisper是一个通用…

HAProxy实现负载均衡

目录 一、HAProxy介绍 二、环境准备 三、实验拓扑 四、HAProxy部署 五、配置HAProxy状态页面 一、HAProxy介绍 ha-proxy是一款高性能的负载均衡软件&#xff0c;主要是做7层负载均衡&#xff0c;也可以做4层负载均衡。因为其专注于负载均衡这一些事情&#xff0c;因此与ng…

8、如何使用FactoryBean向Spring容器中注册bean?

&#x1f4eb;作者简介&#xff1a;zhz小白 公众号&#xff1a;小白的Java进阶之路 专业技能&#xff1a; 1、Java基础&#xff0c;并精通多线程的开发&#xff0c;熟悉JVM原理 2、熟悉Java基础&#xff0c;并精通多线程的开发&#xff0c;熟悉JVM原理&#xff0c;具备⼀定的线…

openEuler快速入门-openEuler命令行基础操作

系列文章目录 第一章 openEuler快速入门(一)-openEuler操作系统介绍 文章目录系列文章目录前言一、shell是什么二、Linux命令行操作技巧三、基础命令3.1、Linux命令分类3.2、目录和文件3.2.1 相对路径和绝对路径3.2.2 处理目录的常用命令ls&#xff1a;cd&#xff1a;pwd&…

tkinter绘制组件(36)——树状图

tkinter绘制组件&#xff08;36&#xff09;——树状图引言布局函数结构内容数据格式整体框架绘制元素与重绘宽度标识元素展开与闭合完整函数代码效果测试代码最终效果github项目pip下载结语引言 TinUI的第38个元素控件&#xff0c;也是TinUI-4.0-添加的第一个组件&#xff0c…