这是关于一个普通双非本科大一学生的C++的学习记录贴
在此前,我学了一点点C语言还有简单的数据结构,如果有小伙伴想和我一起学习的,可以私信我交流分享学习资料
那么开启正题
今天学习了const成员函数,把类的6个默认成员函数也收尾了,总结并实现了日期类
将const修饰的成员函数称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明该成员函数中不能对类的任何成员进行修改
具体什么情况需要用到const指针呢,我们来观察下面的代码
class Date
{
public:
Date(int year = 0, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
void Print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
void Func(const Date& d) // 这里不用const修饰正常运行,用const编译器报错
{
d.Print();
}
int main()
{
Date d1(2024, 1, 10);
Func(d1);
return 0;
}
实际运用中,我们又经常会用到const来保护数据,难道我们不能用const了吗
答案肯定是否定的,我们首先要搞清楚,为什么上面的代码不能正常运行,在d调用Print函数的时候,涉及到传参,而d是一个被const修饰的对象,传参过去的Print的形参是this指针,虽然它没有改变对象的成员,但是它改变的权限,结合我们以前学的传参注意事项,我们不难发现,这里的传参是权限的放大,这是语法不支持的
void Print(const Date* this)
{
cout << _year << "-" << _month << "-" << _day << endl;
}
但是this指针又是编译器默认写的,我们不能像上面这样写,这样会有"两个"this指针,而c++到底是怎样处理的呢,我们观察如下代码
void Print() const
{
cout << _year << "-" << _month << "-" << _day << endl;
}
C++在成员函数的括号后面加上const,表示这是一个const成员函数,this指针被const修饰,这样就很好的解决了我们的问题
因为非const可以调用const,而const不能调用非const,所以在我们编写成员函数的时候,就应该把能加上const的类尽量加上const来修饰
这里给读者留一些问题
1. const对象可以调用非const成员函数吗?
2. 非const对象可以调用const成员函数吗?
3. const成员函数内可以调用其它的非const成员函数吗?
4. 非const成员函数内可以调用其它的const成员函数吗?
class Date
{
public:
Date* operator&()
{
return this;
}
const Date* operator&() const
{
return this;
}
private:
int _year;
int _month;
int _day;
};
这两个默认成员很简单,一般不需要我们来重载,使用编译器默认取地址重载即可,只有特殊情况才需要我们重载,比如想让别人获取到指定的内容(nullptr , 指定成员的地址)
首先我们把要实现的函数和类的基本成员写在头文件中
class Date
{
public:
//获取某月的天数
int GetMonthDay(int year, int month)
{
static int days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
if (month == 2
&& ((year % 400 == 0) || ((year % 4 == 0) && (year %100 != 0))))
return 29;
return days[month];
}
//全缺省的构造函数
Date(int year = 0, int month = 1, int day = 1);
//拷贝构造函数
Date(const Date& d);
//赋值运算符重载
Date& operator=(const Date& d);
//逻辑运算符重载
bool operator>(const Date& d) const;
bool operator<(const Date& d) const;
bool operator>=(const Date& d) const;
bool operator<=(const Date& d) const;
bool operator==(const Date& d) const;
bool operator!=(const Date& d) const;
//日期加减运算符重载
Date& operator+=(int day);
Date& operator-=(int day);
Date operator+(int day);
Date operator-(int day);
Date& operator++();//前置
Date operator++(int);//后置
Date& operator--();//前置
Date operator--(int);//后置
//日期减日期 返回天数
int operator-(const Date& d) const;
//析构函数
~Date();
private:
int _year;
int _month;
int _day;
};
首先实现我们最先学的函数
构造函数,拷贝构造函数,析构函数
Date::Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
Date::Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
Date::~Date()
{
_year = 0;
_month = 1;
_day = 1;
}
要注意的是,在类外定义成员函数要加上类名和访问限定符
再实现日期加减运算符重载
Date& Date::operator+=(int day)
{
if (day < 0)
return *this -= -day;
_day += day;
while (_day > GetMonthDay(_year, _month))
{
_day -= GetMonthDay(_year, _month);
_month++;
if (_month == 13)
{
++_year;
_month = 1;
}
}
return *this;
}
Date& Date::operator-=(int day)
{
if (day < 0)
return *this += -day;
_day -= day;
while (day <= 0)
{
--_month;
if (_month == 0)
{
_month = 12;
--_year;
}
_day += GetMonthDay(_year, _month);
}
return *this;
}
Date Date::operator+(int day)
{
Date ret(*this);
ret += day;
return ret;
}
Date Date::operator-(int day)
{
Date ret(*this);
ret -= day;
return ret;
}
Date& Date::operator++()
{
*this += 1;
return *this;
}
Date Date::operator++(int)
{
Date ret(*this);
ret += 1;
return ret;
}
Date& Date::operator--()
{
*this -= 1;
return *this;
}
Date Date::operator--(int)
{
Date ret(*this);
ret -= 1;
return ret;
}
上面代码用到了复用,它让我们减少了工作量,同时减小了维护所需的成本
再实现逻辑运算符重载
bool Date::operator>(const Date& d) const
{
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;
}
return false;
}
bool Date::operator<(const Date& d) const
{
return !(*this >= d);
}
bool Date::operator>=(const Date& d) const
{
return *this > d || *this == d;
}
bool Date::operator<=(const Date& d) const
{
return !(*this > d);
}
bool Date::operator==(const Date& d) const
{
return _year == d._year && _month == d._month && _day == d._day;
}
bool Date::operator!=(const Date& d) const
{
return !(*this == d);
}
再实现赋值运算符重载,为了实现连续赋值,我们函数的返回参数是调用这个函数的类
Date& Date::operator=(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
return *this;
}
最后实现日期和日期之间的减法
因为进制很复杂,我们不能直接暴力相减,于是我们采用了逐值递增,判断相等,返回次数的方法,代码如下
int Date::operator-(const Date& d) const
{
int count = 0;
Date max = *this;
Date min = d;
if (d > *this)
{
max = d;
min = *this;
}
while (max != min)
{
min++;
count++;
}
return count;
}
总结::C++类和对象的基本特性已经基本熟悉了,六个默认成员函数也掌握了,接下来继续深入C++类和对象的学习
今天的博客就到这里了,后续内容明天分享,最近因为考试周原因不能更新太多内容,等考试周结束了再"快马加鞭"
新手第一次写博客,有不对的位置希望大佬们能够指出,也谢谢大家能看到这里,让我们一起学习进步吧!!!