1、默认成员函数
clsaa A{
;
};
函数中没有成员,称为空类
虽然表面上函数中没有任何成员,但是类中有六个默认的成员函数(构造函数、析构函数、拷贝构造函数、赋值重载、取地址重载),构造函数主要负责完成初始化工作。
通过下面的例子详细了解:
#include<iostream>
using namespace std;
class Date{
public:
void setDate(int year,int month,int day)
{
_year = year;
_month = month;
_day = day;
}
void Print(){
printf("%d-%d-%d\n",_year,_month,_day);
}
private:
int _year;
int _month;
int _day;
};
int main(void)
{
Date d1;
d1.setDate(2023,8,17);
d1.Print();
return 0;
}
对于Date类来说,我们可以通过所写的成员函数setDate来设置对象的内容,但是我们每次创建对象,都需要调用setDate函数来设置对象的内容,使我们的工作量大大的增加,那可不可以在创建对象时,直接就把所需要的内容放进去呢,这样会节约我们更多的时间,那么就需要用到我们的构造函数!
1)构造函数的概念
构造函数是一个特殊的成员函数,它的名字与类名相同,可以自己定义所需的构造函数,也可自动生成(创建类时会自动默认生成六个成员函数)
*构造函数的意义:能够保证对象被初始化
2)构造函数的特性
构造函数是特殊的成员函数,主要特征如下:
①构造函数的函数名和类名相同
②构造函数无返回值
③构造函数可以重载
下面我们来看看构造函数的用法:
#include<iostream>
using namespace std;
class Date{
public:
//无参构造函数
Data()
{
_year = 0;
_month = 1;
_day = 1;
}
//有参构造函数
Date(int year,int month,int day)
{
_year = year;
_month = month;
_day = day;
}
void Print()
{
printf("%d-%d-%d\n",_year,_month,_day);
}
private:
int _year;
int _month;
int _day;
};
int main(void)
{
Date d1; //不给参数时会自动调用无参构造
d1.Print();
Date d2(2023,8,17); //给参数后调用有参构造
d2.Print();
return 0;
}
我们可以发现使用构造函数后,在创建对象时就可直接添加所需的内容,不需要再去调用函数,这样节约了我们的时间,也使得我们的代码更加简洁、美观。
***注意:
**①构造函数是特殊的,不是常规的成员函数,不能直接调用
d1.Date( ); 这样是万万不可的,会直接报错
**②通过无参构造函数创建对象,对象后千万不要加括号,无参构造创建对象不加括号!!!
int main(void)
{
Date d1(); //这样就是错误的,千万不能加括号,加括号后变成函数声明
Date d2(2023,8,17); //调用带参构造
}
**③调用带参构造函数,如果没有设置缺省,需要传递相同个数的参数
Date(int _year,int _month,int _day)
{
_year = year;
_month = month;
_day = day;
}
int main(void)
{
Date d1(2022,8); //传入两个参数,但所需的是3个参数,所以最好使用全缺省构造函数
}
**④如果没有定义构造函数,会自动生成一个无参默认构造函数
#include<iostream>
using namespace std;
class Date{
public:
void Print()
{
printf("%d-%d-%d\n",_year,_month,_day);
}
private:
int _year;
int _month;
int _day;
};
int main(void)
{
Date d1; //调用默认生成的构造函数
d1.Print();
return 0;
}
3)默认构造函数
无参构造函数和全缺省构造函数都被称为默认构造函数,并且默认构造函数只能有一个!!!
class Date{
public:
Date(int year = 2023,int month = 8,int day = 18)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
}
***注意:
**①无参构造函数、全缺省构造函数和默认生成的无参构造函数,都可以认为是默认成员函数
**②语法上无参和全缺省可以同时存在,但同时存在也会发生二义性:
#include<iostream>
using namespace std;
class Date{
public:
Date(){
_year = 0;
_month = 1;
_day = 1;
}
Date(int year = 2023,int month = 8,int day = 18)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
int main(void)
{
Date d1; //此时的d1,无法确定调用哪一个构造函数
return 0;
}
所以我们推荐使用全缺省或半缺省
#include<iostream>
using namespace std;
class Date{
public:
Date(int year = 0,int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
void Print(){
printf("%d-%d-%d\n",_year,__month,_day);
}
private:
int _year;
int _month;
int _day;
};
int main(void)
{
Date d1; //如果不传数据,就是缺省值
Date d2(2023);
Date d3(2023,8);
Date d4(2023,8,18);
d1.Print(); //0-1-1
d2.Print(); //2023-1-1
d3.Print(); //2023-8-1
d4.Print(); //2023-8-18
return 0;
}
4)构造函数的特性测试
①无参的构造函数
②全缺省的构造函数
③编译器自己生成的构造函数
(如果没有自己定义构造函数,编译器会自动生成,如果自己定义了,编译器就不会生成!!!)
#include<iostream>
using namespace std;
class Date{
public:
void Print(){
printf("%d-%d-%d\n",_year,_month,_day);
}
private:
int _year;
int _month;
int _day;
};
int main(void)
{
Date d1; //调用默认生成的无参构造
d1.Print();
return 0;
}
看编译器生成的默认构造函数好像并没有什么用,因为只会产生一些随机值
但是,C++把类型分为内置类型(基本类型)和自定义类型
内置类型就是语法已经定义好的类型,如int/char/...(可能我的int main(void)就是这种类型吧)
自定义类型就是我们使用class/struct/union/自己定义的类型
对于自定义类型的处理,会调用默认构造函数(不用参数就可以调的函数)
#include<iostream>
using namespace std;
class Time{
public:
//默认构造函数,不用参数就可以调用
Time(){
cout<<"你好!"<<endl;
_a = 0;
}
private:
int _a;
}
class Date{
public:
private:
//内置类型
int _year;
int _month;
int _day;
//自定义类型
Time time; //对自定义类型处理,此时会调用默认构造函数Time(){...}
};
int main(void){
Date d1;
return 0;
}
***如果没有默认构造函数(不用参数就可以调用的构造函数),就会报错!!!
①那我们故意写个带参的构造函数:
#include <iostream>
using namespace std;
class A{
public:
//如果没有默认的构造函数,就会报错!!!
A(int a) //故意给个参数
{
cout<<"你好!"<<endl;
}
private:
int _a;
}
class Date{
public:
private:
int _year;
int _month;
int _day;
A _aa;
};
int main(void)
{
Date d1;
return 0;
}
②我们不写,自动生成一个构造函数
#include <iostream>
using namespace std;
class A{
public:
private:
int _a;
}
class Date{
public:
private:
int _year;
int _month;
int _day;
A _aa;
};
int main(void)
{
Date d1;
return 0;
}