构造函数
类当中有6个默认成员函数 不管我们有没有定义成员函数 都会有这6个默认的成员函数
- 构造函数用来初始化
- 析构函数用来清理
- 拷贝函数是 使用同类对象初始化创建对象
- 赋值重载主要是吧一个对象赋值给另一个对象
- 取地址重载主要是普通对象和const对象取地址, 这两个默认函数很少会自己实现
1. 构造函数:
- 作用 : 初始化对象的成员 (相当于这个空间已经有内容了, 构造函数是专门去初始化成员变量的)
- 构造函数名与类名相同, 无返回值, 可以重载
- 如果不显示定义构造函数, 编译器会自动生成一个默认的构造函数(默认构造的函数是无参的) 若是有显示定义的构造函数, 编译器就不会再去生成一个默认构造函数, 除非我们自己定义个无参构造函数
2. 构造函数的产生
- 要么不写, 编译器自己生成;
- 无参构造;
- 全缺省(所有的参数都被初始化了)
-
全缺省的也算是默认构造函数, 但是默认函数只用存在一个, 一般会写全缺省的构造函数, 其有两个作用 ,一可以是默认构造 二还是带参构造,
-
创建对象时, 编译器根据参数的个数自动调用对应参数个数的构造函数(有参的调有参的, 无参的调无参的) 编译器自动调用构造函数来初始化, 我们自己不能显式调用, 有了构造函数就不用再写设置函数
class Date{
public:
// 下面这些就是构造函数 函数名和类名是相同的 且没有返回值 还可以重载 --> 构造函数是有多个的
// 不需要我们亲自去调用, 创建对象的时候编译器亲自去调用
Date(int year, int month, int day){
this->_year = year;
_month = month;
_day = day;
}
// 这是全缺省的构造函数
Date(int year = 1, int month = 1, int day = 1){
//Date(int year, int month, int day){
->_year = year;
_month = month;
_day = day;
cout << "Date(int year = 1, int month = 1, int day = 1)" << endl;
}
// 这是构造函数的重载 这个供有一个参数的对象调用
Date(int year){
_year = year;
}
//重载的构造函数, 无参的为默认构造 只供无参对象调用 前面有了全缺省 这里就不需要写无参构造了
//Date(){
// cout << "Date()" << endl;
// }
private:
int _year;
int _month;
int _day;
};
void test(){
// 如果我们不显示定义, 编辑器会默认生成无参构造函数
Date d1, d2; // 这行代码相当于是类的实例化 这两个对象的内容是空的
// 这里没有显式定义, 但是也调用了无参构造 这里的d1, d2为无参的对象
d1.Display(); // 没有设置函数参数之前对象的内容是随机值
d2.Display();
d1.SetDate(2018, 5, 1); // 这里才是对成员变量的初始化
d2.SetDate(2018, 7, 1);
// 相比上面的初始化 构造函数就更简单的了,
Date d1(2020, 5, 8); // 在运行到这里(实例化对象)时, 编译器会自动调用构造函数
Date d2(2020, 5, 10); // 这下就不用再去写设置函数(setData)了
// 同时我们并不能显式的去调用构造函数
// d1.Date(2020, 5, 10); 是错的
Date d3; // 这里会调无参构造, 成功创建取餐对象
Date d3(); // 这个不是无参构造, 相当于是声明了一个函数.
//这个函数没有参数 返回值为Date 并没有实际指令 和调用
}
-
调用无参构造时后面不能加(); 这个Data a(); 相当于是一个函数的声明
-
若我们没有显示定义构造函数 则可以成功创建无参对象, 因为编译器会默认定义一个无参构造函数; 若我们显示定义了构造函数,编译器就不会再定义无参构造了, 而则这里就创建无参对象就会失败了, 因为没有无参构造函数供他调用; 若此时还需要创建无参对象 则就需要再次显示定义无参构造函数
-
在已经显示定义了构造函数时, 要先创建无参对象, 前提必须自己再显式定义一个无参构造函数,
-
没有实际的指令 如果类中有自定义成员, 当前对象会去自动调用自定义成员的默认构造函数 完成对自定义成员的初始化
3. 自定义类型成员的调用默认构造函数
关于编译器生成的默认成员函数,大家会有疑惑:在我们不实现构造函数的情况下,编译器会生成默认的构造函数。但是看起来默认构造函数又没什么用?d对象调用了编译器生成的默认构造函数,但是d对象year/month/_day,依旧是随机值。也就说在这里编译器生成的默认构造函数并没有什么卵用??
- 解答:C++把类型分成内置类型(基本类型)和自定义类型。内置类型就是语法已经定义好的类型:如int/char…; 而自定义类型就是我们使用class/struct/union自己定义的类型,看看下面的程序,就会发现编译器生成默认的构造函数会对自定类型成员_t调用的它的默认成员函数
class E{
public:
//如果有自定义成员,当前类的构造函数会自动调用自定义成员的默认构造函数,完成自定义成员的初始化
E(){
}
E(int a){
}
// 这两个都是有错的, 调不动E的默认构造函数
// 如果上述 Date 类 中不存在 Date 的默认构造, 就会造成编译错误
private:
Date _d; // 会去调用Date的默认构造函数,完成成员的初始化,
};
void test2(){
E e; //编译器会自动生成一个无参的默认构造
E e2(2);// 调带参构造
}
- 测试 test2 中, 对象e会先进入E中调用无参构造函数, 然后再去Date类中调用Date的默认构造函数 完成自定义成员Date _d的初始化 , 然后再返回到E中结束无参构造函数的调用; 对象e2会先进入E中调用带参构造, 然后进入Date类中调用Date的带参构造,完成自定义成员的初始化, 然后再返回到E中结束带参构造的调用.