C++从入门到起飞之——const成员函数&Date类实现 全方位剖析!

秋风起,再归来~ 2024-07-29 13:05:03 阅读 99

🌈个人主页:秋风起,再归来~

🔥系列专栏:C++从入门到起飞          

🔖克心守己,律己则安

代码链接:这篇文章代码的所有代码都在我的gitee仓库里面啦,需要的小伙伴点击自取哦~

目录

1、const成员函数

2、取地址运算符重载

3、日期类的实现 

3.1Date.h

3.2Date.cpp

0、检查日期是否有效

1、获取某年某月的天数 

 2、全缺省的构造函数

3、拷贝构造函数 

 4、赋值运算符重载 

   5、析构函数

 6、日期+=天数

7、日期+天数

8、日期-天数 

 9、日期-=天数

 10、前置++ 

 11、后置++

12、 后置--

13、 前置--

14、>运算符重载 

15、==运算符重载 

16、 >=运算符重载 

 17、<运算符重载

18、<=运算符重载 

19、!=运算符重载 

20、日期-日期 返回天数 

21、流插入函数重载 

22、流提取函数重载 

3.3Test.cpp

4.完结散花


1、const成员函数

• 将const修饰的成员函数称之为const成员函数,const修饰成员函数放到成员函数参数列表的后 ⾯。

• const实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进⾏修改。 const修饰Date类的Print成员函数,Print隐含的this指针由 Date* const this 变为 const Date* const this

<code>#include<iostream>

using namespace std;

class Date

{

public:

Date(int year = 1, int month = 1, int day = 1)

{

_year = year;

_month = month;

_day = day;

}

// void Print(const Date* const this) const

void Print() const

{

cout << _year << "-" << _month << "-" << _day << endl;

}

private:

int _year;

int _month;

int _day;

};

int main()

{

// 这⾥⾮const对象也可以调⽤const成员函数是⼀种权限的缩⼩

Date d1(2024, 7, 5);

d1.Print();

const Date d2(2024, 8, 5);

d2.Print();

return 0;

}

2、取地址运算符重载

取地址运算符重载分为普通取地址运算符重载和const取地址运算符重载。

class Date

{

public:

Date* operator&()

{

return this;

// return nullptr;

}

const Date* operator&()const

{

return this;

// return nullptr;

}

private:

int _year; // 年

int _month; // ⽉

int _day; // ⽇

};

⼀般这两个函数编译器⾃动 ⽣成的就可以够我们⽤了,不需要去显⽰实现。除⾮⼀些很特殊的场景,⽐如我们不想让别⼈取到当 前类对象的地址,就可以⾃⼰实现⼀份,胡乱返回⼀个地址。

class Date

{

public:

Date* operator&()

{

return (Date*)0x11223344;

// return nullptr;

}

const Date* operator&()const

{

return (Date*)0x11223344;

// return nullptr;

}

private:

int _year; // 年

int _month; // ⽉

int _day; // ⽇

};

int main()

{

Date d1, d2;

cout << &d1 <<endl<< &d2 << endl;

return 0;

}

 俩个对象的地址都是胡乱返回的(真的损!)

3、日期类的实现 

3.1Date.h

为了便于代码的可读性,我们在日期类中将我们目前需要的成员函数进行声明和定义分离!

下面我们先在日期类(Date.h)中声明了我们要完成的一些功能(成员函数)

<code>#pragma once

#define _CRT_SECURE_NO_WARNINGS

#include<iostream>

#include<assert.h>

using namespace std;

class Date

{

public:

void Print()

{

cout << _year << "-" << _month << "-" << _day << endl;

}

// 0、检查日期是否有效

bool CheckDate();

// 1、获取某年某月的天数

int GetMonthDay(int year, int month);

// 2、全缺省的构造函数

Date(int year = 1900, int month = 1, int day = 1);

// 3、拷贝构造函数

Date(const Date& d);

// 4、赋值运算符重载

Date& operator=(const Date& d);

// 5、析构函数

~Date();

// 6、日期+=天数

Date& operator+=(int day);

// 7、日期+天数

Date operator+(int day)const;

// 8、日期-天数

Date operator-(int day)const;

// 9、日期-=天数

Date& operator-=(int day);

// 10、前置++

Date& operator++();

// 11、后置++

Date operator++(int);

// 12、后置--

Date operator--(int);

// 13、前置--

Date& operator--();

// 14、>运算符重载

bool operator>(const Date& d)const;

// 15、==运算符重载

bool operator==(const Date& d)const;

//16、 >=运算符重载

bool operator >= (const Date& d)const;

// 17、<运算符重载

bool operator < (const Date& d)const;

// 18、<=运算符重载

bool operator <= (const Date& d)const;

// 19、!=运算符重载

bool operator != (const Date& d)const;

// 20、日期-日期 返回天数

int operator-(const Date& d)const;

// 21、流插入函数重载

friend ostream& operator<<(ostream& out, const Date& d);

// 22、流提取函数重载

friend istream& operator>>(istream& in, Date& d);

private:

int _year;

int _month;

int _day;

};

3.2Date.cpp

好啦!接下来我们就在Date.cpp这个文件中定义我们要实现的全部成员函数!

0、检查日期是否有效

// 0、检查日期是否有效

bool Date::CheckDate()

{

if (_month < 1 || _month > 12

|| _day < 1 || _day > GetMonthDay(_year, _month))

{

return false;

}

else

{

return true;

}

}

1、获取某年某月的天数 

// 1、获取某年某月的天数

// 因为会被多次调用,所以直接在类里面定义(默认是inline)

int GetMonthDay(int year, int month)

{

assert(month > 0 && month < 13);

static int monthDayArray[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 29;

}

else

{

return monthDayArray[month];

}

}

因为会被多次调用,所以直接在类里面定义(默认是inline),这样我们就可以避免频繁的调用该函数建立栈帧,从而提高性能!

 2、全缺省的构造函数

这里需要注意在声明中写了缺省值后,定义时不能再写缺省值!

// 2、全缺省的构造函数

Date::Date(int year , int month , int day )

{

_year = year;

_month = month;

_day = day;

if (!CheckDate())

{

cout << "非法日期:";

Print();

}

}

3、拷贝构造函数 

// 3、拷贝构造函数

Date::Date(const Date& d)

{

_year = d._year;

_month = d._month;

_day = d._day;

}

 4、赋值运算符重载 

// 4、赋值运算符重载

Date& Date::operator=(const Date& d)

{

if (this != &d)

{

_year = d._year;

_month = d._month;

_day = d._day;

}

return *this;

}

   5、析构函数

Date类其实没有必要显示自定义析构函数!

// 5、析构函数

Date::~Date()

{

//cout << "~Date()" << endl;

}

 6、日期+=天数

// 6、日期+=天数

Date& Date::operator+=(int day)

{

_day += day;

while (_day > GetMonthDay(_year,_month))

{

_day -= GetMonthDay(_year, _month);

_month++;

if (_month > 12)

{

_month = 1;

_year++;

}

}

return *this;

}

7、日期+天数

这里复用了+=的代码!

// 7、日期+天数

Date Date::operator+(int day) const

{

Date tmp = *this;

tmp += day;

return tmp;

}

8、日期-天数 

// 8、日期-天数

Date Date::operator-(int day)const

{

Date tmp = *this;

tmp -= day;

return tmp;

}

 9、日期-=天数

// 9、日期-=天数

Date& Date::operator-=(int day)

{

_day -= day;

while (_day < 0)

{

_month--;

_day += GetMonthDay(_year, _month);

if (_month == 0)

{

_month = 12;

_year--;

}

}

return *this;

}

 10、前置++ 

// 10、前置++

Date& Date::operator++()

{

*this += 1;

return *this;

}

 11、后置++

为了区别前置++和后置++,C++规定后置++多一个参数(int)以示区分!

// 11、后置++

Date Date::operator++(int)

{

Date tmp = *this;

*this += 1;

return tmp;

}

12、 后置--

// 12、后置--

Date Date::operator--(int)

{

Date tmp = *this;

*this -= 1;

return tmp;

}

13、 前置--

// 13、前置--

Date& Date::operator--()

{

*this -= 1;

return *this;

}

14、>运算符重载 

// 14、>运算符重载

bool Date::operator>(const Date& d)const

{

if (_year > d._year)

{

return true;

}

else if (_year == d._year)

{

if (_month > d._month)

{

return true;

}

else if (_month == d._month)

{

return _day > d._day;

}

}

return false;

}

15、==运算符重载 

// 15、==运算符重载

bool Date::operator==(const Date& d)const

{

return _year == d._year

&& _month == d._month

&& _day == d._day;

}

16、 >=运算符重载 

//16、 >=运算符重载

bool Date::operator >= (const Date& d)const

{

return *this > d || *this == d;

}

 17、<运算符重载

// 17、<运算符重载

bool Date::operator < (const Date& d)const

{

return !(*this >= d);

}

18、<=运算符重载 

// 18、<=运算符重载

bool Date::operator <= (const Date& d)const

{

return *this < d || *this == d;

}

19、!=运算符重载 

// 19、!=运算符重载

bool Date::operator != (const Date& d)const

{

return !(*this == d);

}

20、日期-日期 返回天数 

// 20、日期-日期 返回天数

int Date::operator-(const Date& d)const

{

Date max = *this;

Date min = d;

int flag = 1;

if (*this < d)

{

max = d;

min = *this;

flag = -1;

}

int n = 0;

while (min != max)

{

++min;

++n;

}

return n * flag;

}

21、流插入函数重载 

// 21、流插入函数重载

ostream& operator<<(ostream& out,const Date& d)

{

cout << d._year << "年" << d._month << "月" << d._day << "日" << endl;

return out;

}

为什么这个函数不定义为成员函数,反而要在全局中定义呢?

其实我们也是可以在类里面声明定义的?不过这里头会出现一些小问题!

// 21、流插入函数重载

ostream& operator<<(ostream& out)

{

cout << _year << "年" << _month << "月" << _day << "日" << endl;

return out;

}

// 22、流提取函数重载

istream& operator>>(istream& in)

{

while (1)

{

cout << "请输入合法日期>" << endl;

cout << "年:";

cin >> _year;

cout << "月:";

cin >> _month;

cout << "日:";

cin >> _day;

cout << "-----------------" << endl;

if (!CheckDate())

{

cout << "输入非法日期:";

Print();

}

else

{

break;

}

}

return in;

}

当我们定义到类里面时,参数列表中的第一个参数默认是隐含的(Date* const this) ,这恰好与我们在全局外定义的相反,从而导致如果我们在使用该函数时按照我们的习惯去写的话,编译器会直接报错!

必须这样书写! 

<code>Date d1, d2;

d1 >> cin;

d1 << cout;

 我们可以看到这非常不符合我们的习惯!所以我们将他们定义到全局中,方便我们进行参数的调整。但我们又面临如何访问到类内部私有成员的问题,有以下几种方法:

1、将私有成员直接放开为public(最挫的方法)

2、提供get方法得到私有成员

3、使用友元函数

4、重载为成员函数(这里因参数问题就不可用了)

我这里使用了友元函数的方法(到后面我会具体讲解该函数的!)

22、流提取函数重载 

// 22、流提取函数重载

istream& operator>>(istream& in, Date& d)

{

while (1)

{

cout << "请输入合法日期>" << endl;

cout << "年:";

cin >> d._year;

cout << "月:";

cin >> d._month;

cout << "日:";

cin >> d._day;

cout << "-----------------"<<endl;

if (!d.CheckDate())

{

cout << "输入非法日期:";

d.Print();

}

else

{

break;

}

}

return in;

}

3.3Test.cpp

下面代码是我在实现日期类时的检测(仅供参考)

#include"Date.h"

void Test1()

{

Date d1(2024, 7, 21);

Date d2(2024, 7, 22);

Date d3 = d1;

d3.Print();

d3 = d2;

d3.Print();

Date d4=d3 + 3000;

d4.Print();

}

void Test2()

{

Date d1(2024, 7, 23);

/*d1 -= 100;

d1.Print();*/

/*++d1;

d1.Print();

Date ret=d1++;

ret.Print();

d1.Print();*/

}

void Test3()

{

Date d1(2024, 7, 21);

Date d2(2024, 7, 22);

bool ret = d1 >= d2;

cout << ret << endl;

int ret1 = d1 - d2;

cout << ret1 << endl;

}

void Test4()

{

Date d1(2050, 3, 21);

Date d2(2024, 7, 22);

/*bool ret = d1 >= d2;

cout << ret << endl;*/

int ret1 = d1 - d2;

cout << ret1 << endl;

}

void Test5()

{

Date d1, d2;

cin >> d1 >> d2;

cout << d1 << d2;

}

int main()

{

//Test1();

//Test2();

//Test3();

//Test4();

Test5();

return 0;

}

4.完结散花

好了,这期的分享到这里就结束了~

如果这篇博客对你有帮助的话,可以用你们的小手指点一个免费的赞并收藏起来哟~

如果期待博主下期内容的话,可以点点关注,避免找不到我了呢~

我们下期不见不散~~

​​

​​



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。