class P1
{
};
如果一个类中什么成员都没有,简称空类。
如果这个类是空类,那么编译器就会自动生成6个默认成员函数。
默认函数:用户没有显示实现,是编译器自动实现的。
函数名与类名相同。
无返回值。
对象实例化时编译器自动调用对应的构造函数。
构造函数可以重载
代码演示:
class Time
{
public:
//无参构造函数
Time()
{
cout << "day" << endl;
}
//全缺省参数构造函数
Time(int d=10)
{
_d=d;
}
private:
int _d;
};
class P1
{
private:
int a=1;
Time c; //内置类型
};
int main()
{
P1 d1;
return 0;
}
用户显式定义编译器将不再生成。
构造函数会对自定类型成员调用的它的默认成员函数
注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为
是默认构造函数,默认构造函数只能有一个。
区分好两种类型在构造函数和析构函数中的特点:
内置类型:char/int/ double/ long/ float |
---|
自定义类型:struct、 class |
1. 对象在销毁时会自动调用析构函数,完成对象中资源的清理工作
对比下列代码:
有自定义类型代码演示:
无自定义类型代码演示:
默认生成构造函数,对自定义类型成员,会调用他的默认构造函数
默认生成析构函数,对自定义类型成员,会调用他的析构函数
class Date
{
private:
//缺省值不是初始化,这里是声明位置给缺省参数
int _year = 1970;
int _month = 1;
int _day = 1;
};
int main()
{
Date d;
return 0;
}
概念:拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用
特点:
拷贝构造函数是构造函数的一个重载形式。
拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,
因为会引发无穷递归调用
class Date
{
public:
Date(int year = 1000, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
// Date(const Date d) // 错误的传值写法:编译报错,会引发无穷递归
Date(const Date& d) // 正确写法
{
_year = d._year;
_month = d._month;
_day = d._day;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
Date d2(d1);//把d1拷贝到d2
return 0;
}
传引用传参
Date(const Date& d)
d是d1的别名,就是调用了拷贝构造函数然后赋值。
总结:拷贝构造函数先传参,后调用
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
int GetMonth(int year, int month)
{
assert(month > 0 && month < 13);
int days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
if (month == 2 && (year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
{
return days[month+1];
}
else
{
return days[month];
}
}
Date GetXDay(int x)
{
//调用拷贝构造
//d1 的传参不改变
Date tmp = *this;
tmp._day += x;
while (tmp._day > GetMonth(tmp._year, tmp._month))
{
tmp._day -= GetMonth(tmp._year, tmp._month);
++tmp._month;
if (tmp._month == 13)
{
tmp._year++;
tmp._month = 1;
}
}
return tmp;
}
void print()
{
cout << _year << "年" << _month << "月" << _day << "日" << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1(2023,2,3);
Date d2 = d1.GetXDay(100);
d1.print();
d2.print();
//Date d2(d1);
return 0;
}
浅拷贝
特性:浅拷贝仅仅对值进行拷贝
代码演示:
浅拷贝的用法
class xiaofeng
{
public:
xiaofeng(int _data)
: data(_data)
{}
private:
int data;
};
int main()
{
xiaofeng a(5);
xiaofeng b(1);
b = a;
return 0;
}
深拷贝
class xiaofeng
{
public:
xiaofeng(int size)//构造
:_size(size)
{
_date = new char[_size];
};
//重点
xiaofeng(const xiaofeng& s)//传入s1进行深拷贝
{
_size = s._size;
_date = new char[_size];
strcpy(_date, s._date);
}
~xiaofeng()//析构
{
delete[] _date;
_size = 0;
}
private:
char* _date;
int _size;
};
int main()
{
xiaofeng d1(5);
xiaofeng d2(d1);
return 0;
}