目录
1.初始化列表
2.单参数里面的隐式类型转换
3.多参数的隐式类型转换
4.匿名对象
1.初始化列表
(1)首先看一下初始化列表具体是什么?
这个就是初始化列表的具体形式,对,你没有看错,这个初始化列表里面的函数体部分是空的;
我们的初始化列表就是在形参括号的后面加上冒号,接下来就是三个相同的结构,这三个结构是用逗号分隔开的,这个结构的组成就是成员变量+括号(形参);
(2)我们必须要知道的是,我们一般是把成员变量定义为private实际上这个进行的不是变量的定义,而是变量的声明,变量的定义实际上是在初始化列表的地方进行定义的;
(3)初始化列表,毫无疑问,就是对变量进行初始化的,我们可以对所有的成员变量进行初始化,我们也可以对部分成员进行初始化,就算我们不进行初始化,编译器自动进行的;
编译器对初始化列表的执行顺序不会按照我们写的顺序,而是按照private里面的成员变量声明的顺序,这个通过调试是可以看到的;
(4)我们可以把这个初始化列表和函数体结合起来使用,就像下面的这样:
就是初始化的时候,我们的初始化列表里面只写一部分变量,剩下的变量的初始化可以在函数体里面完成;
(5)再结合一下我们前面提及到的缺省参数,我们的缺省参数是在声明的时候给出来的 (通俗而言就是在写private里面的变量的时候给缺省参数):
这个缺省参数实际上就是传递给了初始化列表,我们是可以验证这个过程的,
(6)下面的就是验证过程,也可以加深我们对于知识的理解:
我这里验证的时候只给了day这个成员变量缺省值1,但是在主函数里面进行对象的创建时,肯定会调用默认的构造函数,并且把2024,5,9这三个参数传给对应的值;
我们进行调试就可以发现,这个过程里面day这个成员变量得知会发生变化的:
上面显示的是变化之后的结果:就是调试的箭头指向26行的时候,监视窗口里面的day是1,当我们的调试箭头指向27行之后,监视窗口里面的day的值就变成了现在的9,可见这个缺省参数的值是传递给了初始化列表的,之后不过这个缺省参数被我们后来的参数给覆盖掉了;
(7)我们建议在进行成员变量的定义的时候使用初始化列表,而且顺序尽量和成员变量声明的顺序一样;实质上初始化列表就是我们的默认构造函数的一部分;
2.单参数里面的隐式类型转换
(1)什么是隐式类型转换,简单的讲,就是把不能类型的变量之间可以相互的赋值但是不会报错,我们通过下面这个简单的例子了解一下:
这个就是隐式类型转换的常见的例子,本来c是int类型的数据,但是他可以接受a这个double类型的数据的赋值,这个过程就发生了隐式类型的转换;
具体原理如下(这个后面的类和对象的隐式类型转换用的也是这个原理):就是我们的a实际上是创建了一个临时变量接受这个a的值,然后再把这个临时变量拷贝给我们这里写的变量c,因为我们的临时变量具有常属性,如果我们的c前面没有const进行修饰,就会报错;
原因就是前面提到的临时变量具有常属性,不可以修改,我们不加const相当于是权限的放大,所以加上const相当于是权限的平移,这样才不会报错;
(2)不仅是内置的数据类型例如int,double存在这种隐式类型的转换,在我们的类和对象里面同样存在这种隐式类型的转换,原理基本上都是差不多的:
上面的这个例子值得我们好好的进行分析:
首先是他使用了这个隐式类型转换的语法,我们同样要在a这个引用的对象前面加上const这样才可以算得上是权限的平移,否则同样会报错;
其次,我们一定要注意这里的a aa2=2这句代码,看似是一个简单的代码,实际上他需要我们好好理解:这里实际上进行了编译器的优化,怎样进行优化的呢?
(3)编译器的优化,想必大家一定了解过,这个编译器的优化就是因为编译器的版本过高 出现的问题,优化的实质就是将一些具体的原理给简化了:
这里的a aa2=2是如何进行优化的呢?底层上来讲,2首先会有一个临时变量进行接收,这个临时变量在执行拷贝构造函数,是拷贝构造函数把2这个是传递给了我们的成员变量;
优化之后是怎样进行的呢?优化之后省去了拷贝的过程和临时变量的创建,直接执行的就是构造函数,我们透过这个打印结果是可以看出来的:
(4)对于这个隐式类型转换,我们是可以避免的,就是我们可以使用一些手段不允许编译器进行上面的隐式类型转换,就是在构造函数前面加上explicit关键字,就可以让编译器无法进行隐式类型转换,加上这个关键字的后果就是我们的不同类型数据之间的赋值就会报错(实际上我们一般不会这样做)。
3.多参数的隐式类型转换
(1)上面介绍的是单参数的隐式类型转换,下面我们看一下多个参数的,唯一的不同就是我们这里使用了大括号,其他的原理都是相同的,这里同样是进行了优化的操作
(2)C++11支持多参数的隐式类型转换。
4.匿名对象
(1)匿名对象,与之对应的就是普通的对象,126行就是一个普通的对象,127行就是定义了一个匿名的对象;
(2)匿名对象一般是针对什么场景进行使用的呢?匿名对象一般是针对的只会使用一次的对象进行使用的;
(3)匿名对象和普通对象的区别:普通对象的生命周期在当前的局部域,匿名对象的生命周期是在这一行,在这里的匿名对象的生命周期就在127行,我们这里可以写一行析构函数打印输出查看这个匿名对象的创建和销毁;
(4)匿名对象怎么用:假如有一个solution函数,我们使用普通的对象,先创建bb2在使用bb2这个对象调用这个solution函数,这里显得很费劲,我们创建这个对象就是为了调用这个solution函数
(5)匿名函数可以不创建对象就可以调用这个函数,如132行里面,b(6)实际上就是默认的构造函数,他在这里就相当于是一个匿名对象(因为我们可以发现匿名对象在创建的时候,和有参数的构造函数的写法是一样的),因此我们的132行相当于是创建匿名对象去调用这个solution函数,我们以后见到理解即可。