- 此处主要记录,c++面向对象这部分知识,有助于快速上手其他语言!
- 永远要记住:限制我们发展的永远是我们自己的认知,而不是别人。
- 心态:同样的环境,同样的氛围,总有人比我们发展的更好,总有人发展的不如我们。
- 首推的学习文档:https://en.cppreference.com/w/
- c++是c的超集,C++增加了很多的头文件,不要在意130
- C++包括四种编程范式:面向过程(STL)、面向对象(类和对象)、泛型编程(模板)、函数式编程(Lambda)
- 实现语言的时候,大多数情况下使用的是面向过程、面向对象的范式;当相关的泛型能提高开发效率的情况下,才考虑使用(泛型、函数式编程)。
- 按照编程范式学习其他编程语言,如java.
- 按照编程范式进行分门别类的学习
- 这部分很灵活,可以用来实现栈,队列等
- 提供了非排序,使用哈希表实现;
- map是排序,使用了红黑树实现
百度+谷歌
阿里+谷歌
#245. 货仓选址->std::vector
-
string的使用
#166. 字符串 *** 作1->std::basic_string
string: find_first_of函数并不是搜素某个特定的字符串,而是搜寻参数字符串中任意一个字符的出现 -
map的使用
#216. 获取姓名并排序1->std::map -
set的使用
#287. 合并果子->std::priority_queue
合并果子和哈夫曼编码之间的关系(一模一样)
哈夫曼解决的是什么问题?求最小的编码长度!
-
使用类封装大整数:#256. 国王游戏->参考答案
微扰
- 封装:我该有的和我该做的
- 继承:叫一声爸爸,开启财富之门
- 多态:我就是我,是不一样的烟火
Fundamental types
类型与变量类型 = 类型 数据 + 类型 *** 作
成员属性与方法C++ class与c struct相比,c++ class 中可以放成员方法,而struct不行。
C 语言的struct有单独的命名空间,所以你甚至可以这样定义一个跟类型名字一样的变量;
- 强调作用范围:控制类外对类内的访问权限。(此处好好理解类内和类外)
- public、private、friend的作用:如,类外重载运算符时,就需要使用friend友元进行声明修饰
- protected简介
- 和java、systemverilog中的package是一个道理,防止命名空间内各命名、标识符冲突。
- 实现一个cout
- cin、cout也是c++实现的一个对象,不是一个类型也不是一个方法,本质上就是一个对象。
- 构造函数:默认构造函数、有参构造函数、转换构造函数、拷贝构造函数
- 转换构造函数(一个参数的有参构造函数):普通的转换构造函数的应用、函数传值过程中的转换构造函数的作用
- 拷贝构造函数:拷贝构造函数的基本使用、拷贝构造为什么传入const引用(因为可能需要处理临时的中间变量,所以传入const;防止套娃现象出现,采用引用传入)、赋值拷贝 *** 作
- 还有一个移动构造函数,c++11帮助c++重回神坛,c++11之前没有将左值和右值区分开。
- 一个有参构造函数也被称为转换构造函数,
- 拷贝构造和拷贝赋值运算符是完全不一样的
- 析构函数:需要资源回收的时候,就需要析构函数
- 工程项目中,构造函数和析构函数越简单越好,会使用伪构造函数和伪析构函数,体会工厂模式
- =default和 =delete的作用:明确指出使用或不使用默认的构造函数
C++学习重点:程序处理流程
- 需要析构函数的类也需要拷贝构造函数和拷贝赋值函数。(当类中有些资源是动态申请的,那么它才需要资源回收,可能需要析构函数;但是,对于动态申请出来的这些资源,在发生拷贝行为的时候,通常情况下是发生深拷贝)
- 需要拷贝 *** 作的类也需要赋值 *** 作,反之亦然。(当我们为某个类实现拷贝构造的时候,说明这个类一定是有一些特殊的行为,而这种特殊行为也应该被继承在赋值拷贝运算符之中)
- 析构函数不能是删除的
- 如果一个类有删除的或不可访问的析构函数,那么其默认和拷贝构造函数会定义为删除的。
- 如果一个类有const或引用成员,则不能使用合成的拷贝赋值 *** 作。
这是程序设计的逻辑,先构造的可能为后构造的提供依赖。
转换构造函数(一个参数的构造函数)调用拷贝赋值运算符,会生成临时匿名对象(调用移动构造函数)
拷贝构造函数 和 拷贝赋值运算符- 注意分析拷贝构造和拷贝赋值运算符!
- 在构造对象时,调用的是拷贝构造函数;在给已有对象赋值时,调用拷贝赋值运算符
- 拷贝构造一定要const修饰,为了兼容处理两种场景(传入的被拷贝对象是const和非const类型)
- 提供右值引用的复制构造函数的好处,就是 可以节省很多复制对象的开销 ,调用右值引用的复制构造函数,我们可以简单地认为对象直接跑过去了,并没有发生任何复制。
C++实现的深拷贝
new和malloc的区别(原地构造?实现深拷贝用的还挺多)- new构造的时候会调用构造函数并且会初始化
- delete会自动调用析构函数
- 成员属性和方法(对象)
- 类属性和方法(类)
- 类属性:所有对象访问的都一样,不能使用this指针。定义的时候在前面加上static,全局区?
- 注意辨别:类属性的声明和定义。
- 可以通过域限定符和对象去调用
- const类型的方法与mutable关键字:const声明是为了说明不修改对象内部任何成员属性,主要是给const类型对象使用;mutable就是为了在上述const的修饰下,某些成员属性仍然可以被修改。
- 不对当前属性进行更改。
- const对象不能调用非const对象的方法。
- const类型方法不能调用非const类型方法
- const声明是为了说明不修改对象内部任何成员属性,主要是给const类型对象使用
- 引用在定义的时候要绑定
- c++中只是保留了struct关键字,与class的底层实现基本一样。唯一不同的就是默认访问权限不同,struct默认public,class默认private。
- 为什么要保留struct关键字?
- 为什么默认访问权限public?
- 考虑到语言推广成本,收获c用户群体
- 开辟对象数据区、匹配构造函数、完成构造
- 开辟对象数据区、匹配拷贝构造函数、完成构造
一个作用域内几个函数名字相同,但是参数列表不同,称为函数重载。(与返回值无关)
重载运算符:注意思考返回引用的作用是什么?
一般需要实现连等 *** 作,对象
- 普通运算符重载
- 重载cout的左移运算符
- 普通运算符重载
- 重载下列三个符号,得到的特殊命名:
[] 数组对象 () 函数对象 -> 指针对象其他重载的知识点 不能重载的5个运算符(五大创世宝石)
- .成员引用运算符
- .*成员指针引用运算符
- sizeof运算符
- ?:唯一的三目运算符
- ::作用域 *** 作符
- ()函数括号运算符(函数对象)
- []数组方括号运算符(数组对象)
- ->间接引用运算符(指针对象)
- =赋值运算符
- 正常情况的拷贝 *** 作
- 一次优化的情况
- 二次优化的情况
- g++使用 -nfo-elide-constructors 选项关掉返回值优化
- 逻辑是优化掉,临时匿名对象!
- 如果没有这个 *** 作,可能是被编译器优化掉了
- 大多数编译器会对拷贝构造函数进行返回值优化(替换this指针完成)
std::shared_ptr -----> c++实现简单的智能指针
## 继承子类将父类所有的属性和方法都继承过来
继承-子类的访问权限
继承权限不影响子类对父类内容的访问?
继承权限影响类外部访问子类内部继承自父类这些属性的访问权限
- 在具有继承关系的情况下,当咱们子类实现拷贝构造的时候,需要显式性的去调用父类的构造函数
- 怎么实现子类的重载赋值运算符呢?
- 内存会重复?
- 实际情况下,一个真实基类吗,多个功能性基类,
- 思考与虚继承的配合。
代码不是能用就行!命名非常重要!
如果需要多个不允许拷贝的类,不推荐直接把各个拷贝函数delete掉,建议各个类继承自一个不允许拷贝的类!
C++多态例子:virtual、override、final
- 普通成员跟着类走,在编译期就已经确定了
- 虚函数跟着对象走,在运行期确定,在编译期不能确定
- virtual 、 override和final的关键字的配合,控制是否覆盖父类同名方法,override是为了规范代码的语义,不是必须要写的,final禁止子类中出现与父类同名的函数,终止虚函数
- final:禁止类继承、禁止虚函数重载
- 为什么要有这个关键字?
- final关键字的应用场景:父类中有一个方法需要在所有地方都表示的一模一样,不想让子类去修改,就把相关函数标记成final
对象的前8个字节,存储的是一个虚函数表的地址,可以通过修改对象头8个字节的地址来修改虚函数表,从而调用不同的虚函数。如 ((void **)(&b))[0] = ((void **)(&c))[0]就是把b的虚函数表修改成c的虚函数表了,调用的是c的方法
- this指针其实是底层隐藏的函数
- 函数指针
- c++ 成员函数指针
- 普通方法为什么不能存储成员方法地址?因为它有默认的this指针
- 将基类的地址转换成其派生类的地址
- dynamic_cast是运行期的行为
- dynamic_cast与虚函数表是有关系的
普通成员方法是跟着类走的,为了让其跟着对象走,就要设置成virtual
- 规范析构顺序,使用虚析构函数
- virtual void run()=0,修饰之后必须在派生类中重写!
- C++实现优先队列例子:用堆和队列分别实现
- 请实现一个可以自定义哈希函数的哈希表类:哈希函数包括函数、函数对象、Lambda表达式
- 扩容哈希表
- 在c语言中,用来说明局部的自动变量,当前变量的生存周期是编译器自动决定的,定义它的时候就产生了,出作用域的时候就回收了。(和局部变量一样)
- c++11中, 使用auto方便遍历容器,在编译期就确定了,与sv中的foreach是一样的功能,typeid(x).name()可以查看属性;
- auto不能作为函数参数;不能作为模板参数;不能定义数组;不能用于非静态成员属性;
-
const 运行期常量
-
与const关键字的区别:一个是编译期常量,一个是运行期常量。
-
修饰全局函数、修饰普通函数、修饰构造函数
-
在模板中也会与decltype来搭配使用
- NULL在C与C++中的区别
- C++中的NULL所带来的的歧义:func(int),func(int *)
- nullptr是空指针更准确、无歧义的语义表达
值类别
- C++左右值(引用)示例
- C++引用绑定顺序
- 左值与右值
到了代码的下一行,是否可以通过单一变量访问到值:能访问到就是左值,不能就是右值、(判断不严谨,但是可以用) - 左值引用与右值引用
- 非const变量绑定引用优先顺序
- const变量绑定优先顺序
- 左值引用,使用T&,只能绑定左值
- 右值引用,使用T&&,只能绑定右值
- 常量左值,使用const T&,既可以绑定左值又可以绑定右值
- 已命名的右值引用,编译器会认为是个左值
- 编译器有返回值优化,但不要过于依赖
- 完美转换,主要在模板当中使用,
- forward就是一个类型转换,
- move主要把一个左值或者右值转换成一个右值
左绑左,右绑右;不管咋,先看const;const Type t可以绑定所有类型数据
move constructor 移动构造- 把一个右值转换成左值
- 在战场上,死兵的武器直接抢过来使用
模板在编译期完成完整的运算,其他的一般在运行期。
程序 = 算法 + 数据结构
数据结构: 能够存储任意类型
算法:能够存储 *** 作存储任意类型数据的数据结构
面向过程编程:用模板实现函数过程
面向对象编程:用模板实现类
模板文件在编译阶段就干掉了,必须写在头文件中!
返回值后置
- 自己可以实现一个vector练习练习
- C++使用move实现vector
T&&传入引用类型,
引用折叠:出现偶数个&叫右值引用,出现奇数个叫左值引用。
设计一个可以解析变参列表的工具,例如使用变参列表中的第二个类型定义一个变量。
# 其他内容 异常 C++线程简单使用std::thread
bind简单使用 function- 企业不欠你的,不要带有学生思维意识,一年四季都有实习,随时准备一份简历
- 大量的投递简历,填写自己真实的简历,都能获得大量的面试机会,撩要大胆,“渣男”思维
- 自信是需要建立的,从小公司开始积累经验和面试机会,要有责任感,不要逃违约金。
- 简历:留联系方式、在学校后面可以做特殊标记,减少废话(自我评价没用、年龄不要写、党员、籍贯没用)、个人技能一定要展开来写;多写客观因素、少主观因素;如果要证明c++这一块,可以写实现过stl中的某些东西,掌握了哪些知识点,算法数据结构、网络编程:掌握哪些数据结构,掌握哪些 排序算法,高级数据结构掌握到什么程度,比如了解红黑树呢还是实现红黑树?
- 实现过linux下的某些命令,比如ls、cp、cat、find,自己实现pwd等命令;
- 项目经历,是为了证明你在某些技能上是擅长的,不要写的浮夸
- 要证明自己是想做技术的,对技术是热爱的,态度大于能力,以严谨的态度面对技术
- 大公司造轮子,小公司用轮子
- 面经的知识在于背,不在于会,不要只盯于c++开发:后端、后端、服务器、c++软件开发。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)