侯捷C++个人学习笔记面向对象Part2

conversion function,转换函数

转换函数详细讲解链接
在C++中 当类的构造函数参数只有一个内置类型的形参或除了第一个形参外其他的参数都有默认值时,允许把这种内置类型赋值给类对象,这是一种隐试类型转换。
在这里插入图片描述
fraction分数,分子除以分母就是一个double值
operator double函数的意思就是当fraction对象需要变成double的时候就可以调用此函数,由于分子分母都不会改变因此给operator double函数加上const。此时当fraction对象参与double时都会自动调用此函数变成double类型
只要你认为合理,你就可以添加转换函数。

double d = 4 + f;这一语句会首先查找Fraction是否有重载操作符 operator + (double, Fraction) 的函数,由于没有,所以调用会转换函数operator double() const。

one-argument ctor,仅需要一个实参的构造函数

non-explicit,不明确的

表示在某些情况下可以隐性的将非fraction对象通过构造函数转换成fraction对象
在这里插入图片描述
d2=f+4,+符号左边是fraction对象,fraction类中有写operator+的函数必须与相同的fraction对象相加,因此考虑将4转为fraction对象于是调用蓝色部分的构造函数将4转换成fraction(4,1)
在这里插入图片描述
如果这两个函数并存,这时候编译器就不知道转换f还是4就会报错
只要某个操作对于编译器来说有不止一条路可行,则编译器就会报错

explicit,明确的

表示不可以隐性的转换对象,例如不能再将3转换成3/1的fraction对象
在这里插入图片描述
此时4就不会再变成fraction对象
在这里插入图片描述
bool表示vector(容器)传出来的值是真或假,对操作符[]重载的意义在于判断传出的某一个位置的值如第三个位置或者第一百个位置的值是真或假,而传出来的是reference对象,此对象对应的是_bit_reference,用这个类代表/代理本应该传出的值即bool值。
果然再_bit_reference中有将reference对象转换成bool类型的函数

pointer-like classes,关于智能指针

在这里插入图片描述
一个C++的class会像两种东西
1.像指针
2.像函数
像指针的class其中一定会有一个真正的指针,如上图所示指针所能做出来的动作,这个class也必须要做出来。new Foo得到一个指针放到shared_ptr对象sp中,sp通过构造函数创建出指向Foo对象空间的指针。

智能指针类中一定要有*和->
sp转换成px,其中的星号已经被消耗掉了
->有一个特殊的行为,消耗->符号得到的东西要继续用->符号作用下去

pointer-like classes,关于迭代器

在这里插入图片描述
容器本身带着迭代器,迭代器也是一种智能指针,但与普通智能指针不一样。
迭代器常用于遍历容器
在这里插入图片描述
标准库容器的链表如上图所示,链表的迭代器为node,node就是上一幅图中的link_type node。
我们使用迭代器的时候,使用星号的时候就表示我们想要获取它的值(即node对应的data)。
->重载中的operator*()用的是上面那个函数

function-like classes,所谓仿函数

在这里插入图片描述
identity的意义在于传给它什么他就返回什么
Pair只有两对,第一和第二,是标准库里的函数。first和second不需要一样,一只鸟和一条鱼也可以成为一个Pair。
在我们使用select1st的时候可以写:select1st()(),第一个小括号用于创建临时对象,第二个小括号调用select1st中的函数。
first_type是Pair中定义的类型。

这种class做出来的对象就被称为函数对象
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
上图两个函数的大小理论上都是0。

namespace经验谈

在这里插入图片描述
namespace用于区分来自不同namespace的函数

class template,类模板

在这里插入图片描述
在设计一个class的时候,把一些允许使用者抽离出来的类型抽到外边允许使用者任意指定。
如上图中private中的re和im可以指定为double,int…

function template,函数模板

在这里插入图片描述
只需要写成黄色一行高速编译器,它不需要指明它属于type,因为编译器会自己根据调用的实参进行推导。
如上图stone对象比大小,编译器需要到stone类中找重写操作符<的函数,如果没有找到则会返回错误
模板本身的编译(即未传入函数模板的函数)也只是一个半成品,不能保证之后的真正使用的编译是否能成功

Member Template,成员模板

在这里插入图片描述
黄色一部分是模板里面的一个menber,而它本身就是一个template,于是将此称之为成员模板(member template)
以上三个函数都是构造函数

在这里插入图片描述
上图关系反之则不行。只能将子类放入父类关系里,父类不能放入子类关系里。
如果放入的一对为鲸鱼和麻雀则不行,因为鲸鱼不属于鱼类

在这里插入图片描述
如上图所示,我new一个鲫鱼但我的指针指向鱼类,这种做法叫up-cast。
指针可以,则智能指针也需要可以于是加上了menber template

specialization,模板特化

在这里插入图片描述
泛化的反面就是特化。泛化就是模板,用的时候指定就行了
特化的意思就是你可能会面对独特的东西进行设计。把模板所设定的东西特征化。
第一个框是泛化,第二个框是特化
template<>是因为其中的东西已经被绑定了所以忽略不写。
上图浅绿色表示是一个临时对象,蓝色的小括号启动函数。

partial specialization,模板偏特化(局部特化)

在这里插入图片描述
如上图有两个模板参数,但如果单单使用bool值来使用泛化太浪费了,可以使用如图上第二个框高速编译只是用一个模板参数,因为另一个被绑定了,但是两个都需要写出来。
在这里插入图片描述
如上图一个T可以接收任意类型,另一个T只能接收指针但指向什么都可以。
本来是任意范围,现在变成了指针这就是上图函数的特化

template template parameter,模板模板参数

模板中有一个模板参数是一个class而此class也是用模板
在这里插入图片描述
只有typename位置上,typename和class才可能共通即既可以写typename也可以写class,早先其实没有typename关键字。
上图container是一个代名词是拿第一个模板参数做参数。
如果我希望传入一个容器以及容器的元素类型,那么我的黄色部分必须是一个模板模板参数
如上图中的list本身就是一个模板自身还未确定它错误在写出一个以String为参数的List容器,但容器有第二模板参数(有的还有第三)编译器上语法会出现错误。
在这里插入图片描述
我们使用只需要接收一个模板参数的智能指针来测试。
出错是因为他们自身的特性在这里插入图片描述
虽然上图class是可以传入模板的,但设计过程中没有任何模板参数已经写死了所需要的内容范围

关于C++标准库

在这里插入图片描述
程序=算法+数据结构
在这里插入图片描述
cpprocks.com
百度或者谷歌上图的大字就可以查看编译器支持那些语法
在这里插入图片描述
在这里插入图片描述
测试是否已经支持C++

三个主题

variadic templates(since C++11)

在这里插入图片描述
模板参数可以变化,数目不定的模板参数
typename…即代表数目不定的模板参数。
上图代表接收两组模板参数,第一组是一个,第二组是一包。
上图print的args…又上传给print函数进行递归,将args分为一个和一包函数直到执行完毕。上图执行到42后,因为后面一小包模板参数为0,因此会调用第一个print函数,如果想知道args中有多少成员,可以使用sizeof…(args)的方式

auto(since C++11)

在这里插入图片描述
auto的作用是让编译器根据赋值内容自动判断类型
使用auto的时候必须要赋值

ranged-base for(since C++11)

在这里插入图片描述
这种for循环右边必须是一个容器
for(declaration:collection){}
在第一个示例中,pass by value 如果选择将elem*3,不会影响到容器里面的元素
在第二个示例中,pass by reference引用容器中的元素,此时对elem进行操作会影响到容器元素
引用和指针其实是一种东西,只是表达形式不同,将会详细介绍

Reference

在这里插入图片描述
x是一个整数,它占四个字节
p是一个指针,它指向x。 p是一个变量,这个变量的类型是指向整数类型的指针,指针占四个字节。
r是一个引用,它代表x。reference占多少字节在于它代表的变量是什么类型。reference一定要有初值,且不能改变。
总而言之,指针大小是固定的四个字节,引用大小取决与它代表的变量,引用的地址与变量的地址相同。
在这里插入图片描述
x是double占8个字节,p是指针占4个字节,r是引用占8个字节(和x一样)
在这里插入图片描述
根据传递的方式不同,我们调用函数以及传参的方式也都不同。
reference常用于传递参数。编译器分不清第二个框需要调用哪个函数。上图中灰色部分可以添加const,如果两个imag函数一个加const,一个没有const则他们可以并存。

复合&继承关系下的构造和析构

在这里插入图片描述
dtor是析构函数
在这里插入图片描述
复合为has a
在这里插入图片描述

关于vptr和vtbl(虚指针和虚表)

在这里插入图片描述
虚指针就是指向虚表的指针
只要类中有一个虚函数(无论多少虚函数),对象中就会有一个虚指针。
指向vfunc2的指针地址都相同,凡是子类重写的虚函数都会产生独特的虚指针,存放虚指针的表称为虚表
指针p是通过A *p=new C得到的,这种情况叫向上转型。
如果需要调用C中的虚函数,需要通过p找到vptr再找到vtbl从vtbl里找到指向所需虚函数的虚指针。
上图中的n代表虚表中的第几个,n是多少需要看虚函数创建的时间。
在这里插入图片描述
此处的draw相当于vfunc1。
myLst是一个容器指向父类A里面可以存放A,B,C等类型的对象,通过调用一个函数获得不同的结果这种用法叫多态,draw必须是虚函数才能获得不同的形状。如果draw不是虚函数,那就需要判断指针指的是哪一个才能进行调用。
动态绑定需要有一个指针进行调用,指针需要向上转型(即指针为猪,指向动物),需要指针调用的是虚函数

关于this

在这里插入图片描述
子类的对象调用父类的函数,谁调用函数谁就是this。
所有成员函数一定有一个隐藏的参数this,传进去之后当调用虚函数Serialize时候使用动态绑定(使用指针,向上转型(this指的是子类的对象但调用的父类的函数符合向上转型),调用函数是虚函数)。

关于Dynamic Binding,动态绑定

在这里插入图片描述
a.vfunc1()属于静态绑定,因为没有向上转型
在这里插入图片描述
pa就是向上转型,pa->vfunc1()就属于动态绑定。当pa指向b的地址的时候,仍然属于动态绑定。

关键字const

在这里插入图片描述
const放在小括号()后面,函数主题{}前面放在这个位置的const只能是成员函数这个位置的const意图是告诉编译器我的意图是修饰这个成员函数,这个成员函数不打算改变数据。
在这里插入图片描述
对象调用成员函数的时候由于对象是否是const和成员函数是否是const,就将这个情况分成了四种类型。
这四种情况中,const对象不能调用const成员函数。
凡是需要加const的一定要加const.
使用标准库里的字符串,4个字符串拷贝同一个字符串,那他们可以共享。

上图中basic_string函数,在非const的成员函数中需要考虑COW(copy on write)因为有可能去改变字符串在共享同一个字符串的对象不止一个情况下。由于非const对象可以调用任意成员函数,所以规定如果同时存在const成员函数和非const成员函数,const对象智能调用const成员函数,非const对象只能调用非const成员函数
此情况只有当成员函数存在const和non-const两个版本时候适用

关于new,delete

在这里插入图片描述
new和delete本质上是operator new 和operator delete

重载operator new,operator delete

在这里插入图片描述
这两个操作符重载是全局的,他们的影响很广
new会接收一个大小,delete会接收一个指针。大小是编译器传进来的。
在这里插入图片描述
重载成员delete的时候写不写size_t都无所谓。
在这里插入图片描述

示例

在这里插入图片描述
上图中::delete pf和::new Foo此时调用的是全局的delete函数
在这里插入图片描述
没有[]受到的大小就是1,一个Foo占用12个字节(int+long+string),如果Foo加上一个虚函数则会得到一个指针此时Foo占用16个字节。
如图所示,Foo类new一个数组对象的时候,所需空间是64(此处多出来的4是用于表示有五个元素),调用五次构造函数。
在这里插入图片描述
使用全局的new和delete会调用全局的new和delete函数

重载new(),delete(),拥有placement arguments

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
万一构造过程发生异常,此时就需要调用对应重载的delete

basic_string使用new(extra)扩充申请量

在这里插入图片描述
Rep用于做计数器来计数共享数量

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值