构造函数
构造函数:完成初始化工作。当我们创建一个对象时,要为对象设置初始值。我们来看看下面这个没有构造函数代码,我们为对象设置初始值都要手动调用“SetDate”函数。
class Date
{
public:
void SetDate(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
void Display()
{
cout <<_year<< "-" <<_month << "-"<< _day <<endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1,d2;
d1.SetDate(2018,5,1);
d1.Display();
Date d2;
d2.SetDate(2018,7,1);
d2.Display();
return 0;
}
这样手动完成初始化工作的任务为免也太麻烦了。那有没有不用我们手动调用,由编译器帮我们完成初始化的呢?构造函数就应运而生了,下面我们来看看有构造函数时是怎么完成初始化工作的:
class Date
{
public :
// 1.无参构造函数
Date ()
{}
// 2.带参构造函数
Date (int year, int month , int day )
{
_year = year ;
_month = month ;
_day = day ;
}
private :
int _year ;
int _month ;
int _day ;
};
void TestDate()
{
Date d1; // 调用无参构造函数
Date d2 (2015, 1, 1); // 调用带参的构造函数
// 注意:如果通过无参构造函数创建对象时,对象后面不用跟括号,否则就成了函数声明
// 以下代码的函数:声明了d3函数,该函数无参,返回一个日期类型的对象
Date d3();
}
构造函数是特殊的成员函数,需要注意的是,构造函数的虽然名称叫构造,但是需要注意的是构造函数的主要任务并不是开空间创建对象,而是初始化对象。
其特征如下:
- 函数名与类名相同。
- 无返回值。
- 对象实例化时编译器自动调用对应的构造函数。
- 构造函数可以重载。
构造函数的使用规则
1、如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。
class Date
{
public:
/*
// 如果用户显式定义了构造函数,编译器将不再生成
Date (int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
*/
private:
int _year;
int _month;
int _day;
};
void Test()
{
// 没有定义构造函数,对象也可以创建成功,因此此处调用的是编译器生成的默认构造函数
Date d;
}
2、 无参的构造函数、全缺省的构造函数和编译器自动生成的都称为默认构造函数,并且默认构造函数只能有一个。简单来说:默认构造函数就是:不用参数就可以调用。注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认成员函数。
// 默认构造函数
class Date
{
public:
Date()
{
_year = 1900 ;
_month = 1 ;
_day = 1;
}
Date (int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
private :
int _year ;
int _month ;
int _day ;
};
void Test()
{
Date d1;
}
上面测试函数能通过编译吗?
不能,Date d1 是无参的,会调默认构造函数,而类中有无参的构造函数函数和全缺省的构造函数,这两个都是默认构造函数,这时就存在二义性,编译器不知道去调用哪个构造函数。如果这样定义对象 Date d1(2000,1,1),这样就不会报错,这时只会去调用全缺省的构造函数。
注意:无参的构造函数和全缺省的构造函数是可以同时存在的,只不过用的时候可能会遇到像上面那样的错误,所有我们一般推荐写一个全缺省的构造函数就行。
3.我们不写构造函数,用编译器默认生成构造函数,编译器生成的构造函数对于内置类型不做初始化处理;对于自定类型成员变量会去调用它的默认构造函数初始化,如果自定义成员变量的类中没有默认构造函数就会报错。
class a
{
public:
a()
{
cout << " a()" << endl;
_a = 0;
}
/*a(int a = 0)
{
cout << " a()" << endl;
_a = a;
}*/
private:
int _a;
};
class date
{
public:
private:
// c++里面把类型分为两类:内置类型(基本类型),自定义类型
// 内置类型:int/char/double/指针/内置类型数组 等等
// 自定义类型:struct/class定义的类型
// 我们不写,编译器默认生成构造函数,对于内置类型不做初始化处理
// 对于自定类型成员变量会去调用它的默认构造函数初始化,如果没有默认构造函数就会报错
int _year;
int _month;
int _day;
a _aa;
};
int main()
{
date d1;
return 0;
}
我们调试代码:
这个图说明:我们不写构造函数,用编译器默认生成构造函数,编译器生成的构造函数对对于自定类型成员变量会去调用它的默认构造函数初始化。
这个图说明:我们不写构造函数,用编译器默认生成构造函数,编译器生成的构造函数对于内置类型不做初始化处理