C++类与对象2
类的6个默认构造函数
初始化和清理
- 构造函数主要完成初始化工作
- 析构函数主要完成清理工作
拷贝复制
- 拷贝构造是使用同类对象初始化创建对象
- 赋值重载主要是把一个对象赋值给另一个对象
取地址重载
主要是普通对象和const对象取地址,这两个很少会自己实现。
首先我们先写一段代码
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; }
构造函数
对于date类,我们可以通过SetDate方法对他进行对象成员设置,但显然,每次需要先创建,再设置显得过于繁琐,于是便有了构造函数的设计。创建类对象时编译器自动调用该类的构造函数,保证每一个数据成员都有一个合适的初始值,并且再对象的生命周期内只调用一次。
特性
- 函数名与类名相同
- 无返回值
- 对象实例化时编译器自动调用对应的构造函数
- 构造函数可以重载
// 1.无参构造函数
Date ()
{}
// 2.带参构造函数
Date (int year, int month , int day )
{
_year = year ;
_month = month ;
_day = day ;
}
- 若类中没有显示的给出构造函数,则C++的编译器会自动生成一个无参的默认构造函数,但用户一旦自行定义后,编译器将不再生产
- 无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个(还有我们自己不写会默认生成的构造函数)
- 对于系统自动生成的默认构造函数,我们发现对于int,double等内置类型并不会进行初始化,而对class等自定义类型常量则会进行初始化。
析构函数
析构函数是为了完成资源的清理
特性
- 析构函数名是再类名的前面加上~
- 无参数无返回值
- 一个类只有一个析构函数,若没有显示定义,则系统会默认生成析构函数
- 对象生命周期结束的时候,C++编译器自动调用析构函数
- 默认生成的析构函数只能释放对象本身对应的内存空间,假如类对象有new创造的内存空间,则需要自己假如delete来释放内存空间(因为此时默认析构函数,只释放了指针所占的空间,而并没有释放指针所指向的空间)
拷贝构造函数
创建一个与自身相同的类对象
特性
- 拷贝构造函数是构造函数的一个重载形式
- 拷贝构造函数参数只有一个且必须使用引用传参,使用传值方式会引发无穷递归(传值传参首先需要拷贝构造一个类对象,无限循环)
- 若没有显示定义,系统默认生成的拷贝构造函数执行的是浅拷贝,即按照内存存储的字节序完成拷贝。(若有通过指针指向的内存空间,则会发生错误,因为每一个类对象都会析构,但是因为指针指向了同一块地址,就会出现同一个动态内存空间被析构两次的情况)
- 为应对上述提到的浅拷贝情况,对于特殊的情形,我们需要自己写拷贝构造函数以完成深拷贝。
赋值运算符重载
运算符重载
- 不能连接其他符号来创建新的操作符
- 重载操作符必须有一个类类型或者枚举类型的操作数
- 用于内置类型的操作符,如应用于内置的整型的+不能改变他们的含义
- 作为类成员的重载函数时,形参比操作数数目少一个,因为this指针是默认的
- *、::、sizeof、?:、.这五个运算符不能重载
bool operator==(const Date& d1, const Date& d2) {
return d1._year == d2._year;
&& d1._month == d2._month
&& d1._day == d2._day; }
赋值运算符重载
赋值运算符有些类似拷贝构造
他有几个注意点
- 参数类型为类
- 返回值也为类
- 检测自己是否给自己赋值
- 一个类如果没有显示的定义赋值运算符重载,编译器也会生成一个,但这是按照字节序的浅拷贝。
Date& operator=(const Date& d)
{
if(this != &d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
}
const成员
const修饰类的成员函数
const修饰成员函数本值修饰的是this指针,表明不能对类的任何成员进行修改。
注意
const本值上是缩小权限,所以非const对象可以调用const成员函数,非const成员函数可以调用const成员函数。
取地址及const取地址操作符重载
class Date
{
public :
Date* operator&()
{
return this ;
}
const Date* operator&()const
{
return this ;
}
private :
int _year ; // 年
int _month ; // 月
int _day ; // 日
};