在完成类和对象(一)以及日期类Date的学习后,我们对类和对象已经有了初步了解,现在我们针对部分没有补充完整的知识点,进一步深入学习。
1.初始化列表
在类与对象1C++入门:类与对象(1)-CSDN博客中我们谈到,默认构造函数必须是不传参就能使用的函数:如果没有自己显式实现,会生成默认的构造函数;如果自己显式实现不传参的构造函数,就直接调用;唯独不能写需要显式传参的构造函数,如下:
public: Stack(size_t capacity ) { _array = (DataType*)malloc(sizeof(DataType) * capacity); if (NULL == _array) { perror("malloc申请空间失败!!!"); return; } _capacity = capacity; _size = 0; }
我们之前讲到,可以通过初始化列表的方式完成对这种需要传参的显式实现的构造函数的构造。
初始化列表:以一个 冒号开始 ,接着是一个以 逗号分隔的数据成员列表 ,每个 " 成员变量 " 后面跟 一个放在括号中的初始值或表达式。
冒号开始,逗号分割:
、
初始化列表位于函数体{}和函数头之间,用后面的括号表示所传的参数。
内置类型后面括号中的参数给多少就是多少,自定义类型利用给的参数调动自己对应构造函数
易错:
初始化列表作用是用来传参,传完之后后面必须接上函数名的中括号,否则语法错误
在有了初始化列表的概念之后,我们现在又可以将一个类中的变量的创建分为声明和定义两部分了,就像之前的函数一样:在private下的那一部分我们可以理解为“声明”,在构造函数或初始化列表中就被当作“定义”
初始化列表和函数中的内容也可以混用:
哪些成员应该在初始化列表中初始化?
先给结论,引用、const修饰、没有默认构造的自定义类型成员这三类必须要在初始化列表中定义。
const修饰的成员只有一次初始化的机会(因为一旦被确认就不能再被更改),所以说定义的时候必须初始化,因此我们必须在初始化列表中定义这个const int _x
引用& 同理(引用在第一次赋值之后就不能改变指向)。
引用也是一样:
对象初始化才是定义的地方,也就是初始化列表里
而在class的private下写的那个算是变量的声明
不手动写初始化列表:
不写初始化列表,编译器也会自动生成,并且所有成员都会走一遍该默认生成的初始化列表。
自定义类型成员会走默认构造(编译器悄悄帮你做了,这也是为什么说cpp难学,编译器悄悄做了太多事)
这是一个逻辑闭环。不写的时候自动生成默认构造,默认构造在函数名和函数体之间又自动放了初始化列表,每一个成员都会先走一遍,对于自定义类型,又会调用他的构造函数,我们显式写的是Stack _popst(10),他默认生成的初始化列表调用的是Stack _popst(),因为找不到匹配的,所以就会报错
对于内置类型,如果在初始化列表中写了,就不会再去管private下声明处写的缺省参数,如果没在初始化列表中写, 就会使用这个缺省参数。可通过调试观察。
如下图:既有缺省参数,又显式写了初始化列表,则以初始化列表为准(只有初始化列表中找不到时,才去缺省参数处寻找)
因此,我们可以认为声明处的缺省值其实是个初始化列表用的
此处的“=”只是一个形式,其实际表示意义就是将“=”后面的值作为参数传入初始化列表。
例如 Stack _pushst=10;的意思就是将10
_x依然应该在初始化列表中被初始化,如果没有被初始化,就使用缺省值。
对象模型按照声明顺序存储
2.自定义类型和内置类型的隐式类型转化
不希望隐式转化发生,就加关键字:explicit
多参数的隐式转换:
用花括号括起来
问 为什么要加const的可以打死了。
友元函数 可访问类的私有和保护成员,但 不是类的成员函数友元函数 不能用 const 修饰友元函数 可以在类定义的任何地方声明, 不受类访问限定符限制一个函数可以是多个类的友元函数友元函数的调用与普通函数的调用原理相同