此时赋值操作既可以在手动添加的初始化列表中完成,也可以在函数体中完成赋值。
(1).手动添加的初始化列表中完成赋值
Date(int year = 1, int month = 1, int day = 1)//构造函数
:_year(year),
_month(month),
_day(day)
{
}
Date d1;
d1.Print();
运行结果:
(2).函数体内完成赋值
public:
Date(int year = 1, int month = 1, int day = 1)//构造函数
/* :_year(),
_month(),
_day()*/ //默认参数列表
{
_year = year;
_month = month;
_day = day;
}
Date d1;
d1.Print();
运行结果:
总结:内置类型成员变量的定义(分配内存空间)只能在初始化列表中一次性完成,不管写不写都会有这个过程,手动写可以顺便在定义时赋值。不写编译器的默认参数列表会将成员变量定义为随机值,之后再函数体中再次赋想要的值。
2.自定义类型成员在参数列表中的定义
当我们不手动添加初始化列表,默认的初始化列表会调用自定义类型成员的默认构造函数
例如:当构造函数是这样时
Date(int year = 1, int month = 1, int day = 1)//构造函数
//:_year(),//默认初始化列表
//_month(),
//_day(),
//a() 默认构造函数的调用
{
//构造函数函数体
}
Date d1;
运行结果:
当我们手动写初始化列表时,就可以选择性的调用自定义类型的构造函数,可以是带参的,也可以是默认构造函数。
Date(int year = 1, int month = 1, int day = 1)//构造函数
:_year(year),//默认初始化列表
_month(month),
_day(day),
a(2) //选择调用带参构造函数
此时
Date d1;
运行结果
总结:默认构造函数对自定义类型自动调用自定义类型的默认构造方法本质是默认构造函数的默认初始化列表调用自定义类型的默认构造方法。只要构造方法使用默认初始化列表,对自定义类型就会调用它的默认构造方法。反之,手动添加初始化列表就可以选择性的调用自定义类型的构造方法。
3.初始化列表解决的三大问题
(1)类中的引用成员变量
引用在定义的时候必须初始化,否则会出现编译错误,详见重生之我要学C++第二天_无极太族的博客-CSDN博客
类中的成员都是在初始化列表中定义的,如果成员有引用类型就必须在初始化列表中初始化。
#include<iostream>
using namespace std;
class A
{
public :
A(int a)
{
_a = a;//初始化
}
private:
int& _a;
};
int main()
{
int tmp = 2;
A a(tmp);
return 0;
}
此时,引用_a的定义在默认初始化列表中已经完成,在构造函数函数体中在赋值初始化会导致编译错误(定义处未初始化)。
解决方案:在构造函数中手动添加初始化列表,在初始化列表中定义和初始化一并进行。
A(int a)
:
_a(a)
{
}
(2)const成员变量
const成员变量容易出问题和引用的原理相同。都是定义处必须初始化。
(3)自定义类型成员没有默认构造函数时的问题
我们知道,构造函数不写初始化列表时,默认初始化列表会调用自定义类型的默认构造函数
默认构造函数:
详见:重生之我要学C++第四天_无极太族的博客-CSDN博客
但是如果此时这个自定义类型没有默认构造方法,会出现编译错误。
这时候就必须手动添加参数列表,选择性的调用自定义类型具有的构造方法。
运算符重载的应用
第四天我们学习了运算符重载,在这里举两个例子让读者感受到运算符重载的魅力!
(1)顺序表中的运算符重载
先写一个简陋的顺序表
#include<iostream>
using namespace std;
class Sequence
{
public:
Sequence()
{
//初始化
_a = (int*)malloc(4 * sizeof(int));
_size = 0;
_capcity = 4;
}
void Push(int x)
{
//检查容量:此处忽略
_a[_size] = x;
_size++;
}
void Print()
{
for (int i = 0; i < _size; i++)
{
cout << _a[i] << " ";
}
}
private:
int* _a;
int _size;
int _capcity;
};
int main()
{
Sequence s;//创建顺序表
s.Push(1);//尾插三个数据
s.Push(2);
s.Push(3);
//打印顺序表
s.Print();
return 0;
}
我们可以在类内部将[ ]重载一下
int& operator[](int i)
{
return _a[i];
}
此时,顺序表内的元素就可以像数组一样访问:
int main()
{
Sequence s;//创建顺序表
s.Push(1);//尾插三个数据
s.Push(2);
s.Push(3);
//打印顺序表
cout << s[0]<<s[1]<<s[2]<<endl;
return 0;
}
重载[ ]后,可以让顺序表更加形象,大大增强了代码的可读性。
(2)自定义类型的流插入流提取
用Date类来举例
#include<iostream>
using namespace std;
class Date//类Date
{
public:
Date(int year=1, int month=1, int day=1)//构造函数
{
_year = year;
_month = month;
_day = day;
}
void Print()
{
cout << _year << "年" << _month << "月" << _day << "天" << endl;
}
private:
//成员变量的声明
int _year;//内置类型成员
int _month;
int _day;
};
int main()
{
Date d1(1,1,2);
d1.Print();
return 0;
}
可以使用Print函数来打印日期
先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前在阿里
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Linux运维全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上运维知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
423917)]
[外链图片转存中…(img-yWrletyV-1714395423918)]
[外链图片转存中…(img-WXYkfei3-1714395423918)]
[外链图片转存中…(img-suCcFeoJ-1714395423918)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上运维知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新