构造函数是类的六个默认成员函数之一,这里的默认是指我们不写,编译器会自己生成的。
构造函数其目的是初始化对象,不是开空间。
其特征如下:
1.函数名与类名相同
2.没有返回值,意思是不用在函数前面写void。
3.对象实例化时编译器自动调用相应的构造函数
4.构造函数可以重载
5.构造函数位于公共代码区
以下是我们自己写的构造函数:
class date
{
public:
date()
{
_year=1;
_month=1;
_day=1;
}
private:
int _year;
int _month;
int _day;
};
当我们创建一个date对象的时候,会自动调用这个构造函数。
1.默认生成的构造函数
当我们不自己实现任何一个构造函数时,编译器会自己生成一个无参的构造函数,这个函数会把内置类型不会处理(随机值),除非这个内置类型的成员变量是缺省的(cpp11支持声明给缺省值,而自定义类型会调用其无参的构造函数。一般情况下都需要我们自己写构造函数,只有成员变量全是自定义类型时,可以考虑不写(由于自定义类型我们一般是写了构造函数的)。
2.传参数的构造函数:
date(int year,int month,int day)
{
_year=year;
_month=month;
_day=day;
}
我们来运用一下:
int main()
{
date d1(2025,5,10)
return 0;
}
我们写的date类里面已经有了两个构造函数,当我们实例化类的时候,会根据我们的传参类型自动匹配。
不能这样写:
date d2();
即:没有参数的时候不能加括号,因为编译器分不清这是在定义一个对象还是一个函数的声明(返回值是date的函数声明)。
3.缺省的构造函数:
上面我们实现了一个无参的构造函数,一个带参的构造函数。现在,我们可以通过缺省使这两个函数合并。
date(int year=1,int month=1,int day=1)
{
_year=year;
_month=month;
_day=day;
}
这是一个全缺省的构造函数,当我们将类实例化的时候传参或者不传参,调用的都是这个函数,不过需要注意的是,这个函数与无参的构造函数不能同时存在 ,即使语法上这两个函数构成函数重载了,但是实际调用的时候会出现不传参数时不知道调用哪个函数的情况。
合并成全缺省函数之后更灵活了,可以只传一个参数或者两个参数
date d3(2025);
date d4(2025,5);
date d5(2025,5,10);
关于全缺省在我该专栏的另一篇文章有更详细的讲解C++入门-CSDN博客
4.默认构造函数
默认构造函数就是不用传参数就可以调用的,通常有三种:
编译器自动生成的、全缺省的、无参数的。
5.初始化列表
初始化分为两种方式,一种是函数体内初始化,还有一种是初始化列表。
初始化列表是每个成员定义的地方
class date
{
public:
date(int year,int month,int day)
:_year(year)
,_month(month)
{
_day=day;
}
private:
int _year;//每个成员声明的地方
int _month;
int _day;
};
声明不开空间,只有在对象定义的时候才给整体开空间。(开的空间是整的)
由于每个成员是在初始化列表里面定义的,所以在初始化列表里给每个成员开具体的空间。
初始化列表主要作用:
1.const修饰的成员
由于const变量必须在定义的时候初始化,之后就不能在赋值和修改了,所以,const变量在初始化列表里初始化,构造函数体里面的就不是初始化了,是赋值了。
2.引用
引用也必须在定义的时候初始化
3.自定义类型
当成员里含有自定义类型时,而自定义类型又没有默认构造函数,只有带参的构造函数时,只能调用带参的,这个时候我们就可以在初始化列表里面调用(当处于这个类的无参构造时)。
缺省值与初始化列表
class date
{
public:
date(int year,int month,int day)
:_year(year)
,_month(month)
{
_day=day;
}
private:
int _year=1;//每个成员声明的地方
int _month=1;
int _day=1;
};
当我们在成员变量定义的地方给缺省值时,其实这个缺省值是给初始化列表的,如果初始化列表没有显式地给值就用这个缺省值,如果给了,就用显式的那个值。
初始化列表的初始化顺序:
初始化列表的初始化顺序与其声明的顺序相同,因此,我们在显式的给值时,尽量按照声明的顺序。
需要检查操作是否失败的地方还是需要在函数体里面操作。
注意事项:
1.构造函数实际上是需要我们对其做一些检查的,比如传的参数是否符合实际意义。