✨Blog:不会敲代码的小张:)
推荐专栏:C语言、Cpp️、数据结构初阶
座右铭:“記住,每一天都是一個新的開始”
本章内容:《C++类和对象(中)》的介绍✨
上期我们讲了C++类和对象(上)
如果一个类中什么成员都没有,简称为空类。
空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。
用白话来说就是:我们不写,编译器会自己生成
class Date
{
public:
//构造
Date()
{
_year = 1;
_month = 1;
_day = 1;
}
//构造函数可以重载,如果这里给成全缺省值,和上面的构造也构成重载,但是如果在实例化时不传参,会造成调用不明确
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
如果类中没有显示定义构造函数,则C++编译器会自动生成一个无参默认构造函数,内置类型不做处理,自定义类型会去调用他的默认构造
如何理解上面这句话呢,下面我们来看一段代码
内置类型:
自定义类型:
1.一般情况下,有内置类型成员,就需要自己写构造函数,不能用编译器自己生成
2.如果都是自定义类型成员,可以考虑让编译器自动生成构造函数
如:OJ题,用两个栈实现队列
但是归根结底最开始的自定义类型类型还是自己写了构造函数
结论:
1.一般情况下,构造函数都需要自己写
2.什么情况下不需要写呢?
a.内置类型成员都有缺省值,且初始化符合我们的要要求
b.全是自定义类型,且这些类型都定义了默认构造
可以在类型声明的时候给缺省值:
如果我们没有显示传递值,那么编译器就会使用默认缺省值,相当于备胎
析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。
在现实生活中,可能存在一个与你一样的自己,我们称其为双胞胎
C++规定内置类型传参是直接拷贝,自定义类型传参是先调用拷贝构造完成拷贝。
内置类型:我们不写编译器自己生成,内置类型成员完成值拷贝/浅拷贝
**自定义类型:**自定义类型成员会调用它的拷贝构造
如果要拷贝构造的函数中有malloc出来的空间,需要自己定义深拷贝,否则会指向同一块空间,析构函数就会调用两次,程序就会崩,另外一个问题就是,一个修改,会影响另外一个。
日期-日期//有意义
日期+日期//没意义
是否要运算符重载,取决这个运算符对这个类是否有意义
class Date
{
public:
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
bool operator<(const Date& d)
{
if (_year < d._year)
{
return true;
}
else if (_year == d._year && _month < d._month)
{
return true;
}
else if (_year == d._year && _month == d._month && _day < d._day)
{
return true;
}
else
{
return false;
}
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1(2023, 2, 3);
Date d2(2024, 2, 3);
bool ret = d1 < d2;//自定义类型比较大小,会去调用运算符重载
cout << ret << endl;
return 0;
}
iostream头文件包含ostream和istream,ostream包含operator自定义类型运算符重载,而cout就是调用operator<<函数重载自动匹配内置类型,我们之所以可以使用内置类型比较大小,是因为内置类型是库里面已经实现的。
已经存在的两个对象之间复制拷贝
编译器自己生成的赋值重载,只能完成浅拷贝,如果有malloc出来的对象,需要自己写赋值重载。
默认生成的赋值重载跟拷贝构造是一样的
1.内置类型———值拷贝/浅拷贝
2.自定义类型成员会去调用它的赋值重载
在平常内置类型可以直接使用取地址运算符,但是自定义类型不可以,不过系统会自动生成默认函数,平时默认的就足够使用。
将const修饰的“成员函数”称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。
void Print()const
==
void Print(const Date*this)
但是this指针是隐式的,不能显示修改,所以直接在括号后面加上const。
bool operator==(const Date& d) const//修饰的是*this
{
return _year == d._year
&& _month == d._month
&& _day == d._day;
}
加上const以后,普通对象和const对象都可以掉用,普通对象调用加上const函数,权限缩小
权限缩小可以,但是不能权限放大。
如果没有加上const,而实例化对象是const,则不能正常调用,因为权限可以平移,可以缩小,但是不能放大。
结论: