运算符重载和重载函数

news/2024/11/1 16:35:52/

1.运算符重载的意义

C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
函数名字为:关键字operator后面接需要重载的运算符符号。
函数原型:返回值类型 operator操作符(参数列表)

当您调用一个重载函数或重载运算符时,编译器通过把您所使用的参数类型与定义中的参数类型进行比较,决定选用最合适的定义。选择最合适的重载函数或重载运算符的过程,称为重载决策。

在同一个作用域内,可以声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同。您不能仅通过返回类型的不同来重载函数。

注意:

  • 不能通过连接其他符号来创建新的操作符:比如operator@
  • 重载操作符必须有一个类类型参数
  • 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义
  • 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this
  • .* sizeof ?: . :: #注意以上6个运算符不能重载。切记

2.运算符重载的使用

通过实现一个日期类函数,学习运算符重载的使用

先来写一个类用来实现日期类的创建

class Date
{//友元函数friend ostream& operator<<(ostream& out, const Date& date);friend ostream& operator>>(istream& in, Date& date);
public:Date(int year = 0, int month = 0, int day = 0){_year = year;_month = month;_day = day;cout << "创建" << _year << endl;}~Date(){cout << "销毁" << _year << endl;}//拷贝构造函数Date(Date& date){cout << "1" << endl;_year = date._year;_month = date._month;_day = date._day;}//void Print();//判断两个日期是否相等bool operator==(const Date& days);//判断前一个日期是否大于等于后一个日期bool operator>=(const Date& days);//判断前一个日期是否小于等于后一个日期bool operator<=(const Date& days);//判断前一个日期是否大于后一个日期bool operator>(const Date& days);//判断前一个日期是否小于后一个日期bool operator<(const Date& days);//判断两个日期是否不相等bool operator!=(const Date& days);//日期加一个天数,返回一个日期,改变原日期Date& operator+=(int days);//日期加一个天数,返回另一个日期,原日期不变Date operator+(int days);//日期减天数,返回一个日期,原日期改变Date& operator-=(int days);//日期减日期,返回一个天数int operator-=(Date& days);Date& operator--();Date& operator--(int) ;Date& operator++();Date& operator++(int) ;private:int _year;int _month;int _day;
};//重载流提取
ostream& operator<<(ostream& out, const Date& date);
//重载流插入
ostream& operator>>(istream& in, Date& date);

3.友元函数:(临时插入)

类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。

友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。

如果要声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字 friend。

注意:友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。

说明:

  • 友元函数可访问类的私有和保护成员,但不是类的成员函数
  • 友元函数不能用const修饰
  • 友元函数可以在类定义的任何地方声明,不受类访问限定符限制
  • 一个函数可以是多个类的友元函数
  • 友元函数的调用与普通函数的调用原理相同
     

友元类下次再说

4.日期类函数的实现

4.1打印函数

/打印函数,用下面的流插入流体取实现
//void Date::Print()
//{
//	cout << _year << " "
//		<< _month << " "
//		<< _day << endl;
//}

4.2 比较运算符的实现

//相等
bool Date::operator==(const Date& days) const
{return _year == days._year &&_month == days._month &&_day == days._day;
}
//大于
bool Date::operator>(const Date& days) const
{if (_year > days._year){return true;}else if (_year == days._year &&_month > days._month){return true;}else if (_year == days._year &&_month == days._month &&_day > days._day){return true;}return false;
}
//小于
bool Date::operator<(const Date& days) const
{return !(*this > days && *this == days);
}
//大于等于
bool Date::operator>=(const Date& days) const
{return (*this > days)|| (*this == days);
}
//小于等于
bool Date::operator<=(const Date& days) const
{return !(*this > days);
}
//不等于
bool Date::operator!=(const Date& days) const
{return !(*this == days);
}

4.3加减法的实现

//判断一个月的天数
int GetMonthDay(int _year, int _month)
{static int monthday[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;}return monthday[_month];
}	
//日期加一个天数
Date& Date::operator+=(const int days)
{_day += days;while (_day > GetMonthDay(_year, _month)){_day -= GetMonthDay(_year, _month);_month++;if (_month == 13){_year++;_month = 1;}}return *this;
}
//日期加天数,本身不变
Date Date::operator+(const int days)
{Date tmp(*this);tmp += days;return tmp;
}
//日期减天数,本身改变
Date& Date::operator-=(int days)
{if (days < _day){_day -= days;return *this;}else if (days == _day){_month -= 1;if (_month == 0){_month = 12;_year--;}_day = GetMonthDay(_year, _month);return *this;}else{days -= _day;_month -= 1;if (_month == 0){_month = 12;_year -= 1;}while (days > GetMonthDay(_year, _month)){_month -= 1;if (_month == 0){_month = 12;_year -= 1;}}return *this;}}
Date Date::operator-(int days)
{Date tmp(*this);tmp -= 1;return tmp;
}
//日期减日期
int  Date::operator-=(Date& days)
{//int days = 0;if (*this > days){if(_day>days._day)return _day - days._day;else{return _day + GetMonthDay(_year, _month - 1) - days._day;}}else if (*this == days){return 0;}else{if (_day < days._day)return days._day-_day;else{return days._day+ GetMonthDay(_year, _month - 1) - _day;}}}
//前置日期减减
Date& Date::operator--()
{*this -= 1;return *this;
}
//后置减减,后置加加需要传一个int,语法规定,后置加加也一样
Date& Date::operator--(int)
{Date tmp(*this);tmp -= 1;return *this;
}
//前置加加
Date& Date::operator++()
{*this += 1;return *this;
}
//后置加加
Date& Date::operator++(int)
{Date tmp(*this);tmp += 1;return *this;
}

4.4流提取和流插入

//流插入
ostream& operator<<(ostream& out, const Date& date)
{out << date._year << "年"<< date._month << "月"<< date._day << "日"<< endl;return out;
}
//流提取
ostream& operator>>(istream& in, Date& date)
{in >> date._year >> date._month >> date._day;return cout<<date;
}

这是运算符重载和重载函数的实现,有兴趣的可以自己敲一下。


 


http://www.ppmy.cn/news/60528.html

相关文章

汇编语言学习笔记四

字符 字符是以ASCII码的形式存储的&#xff0c;一个字符对应着8为二进制数&#xff0c;2位16进制数。 所以可以得到对应的字符地址。 assume ds:data data segmentdb hellodb world data endsand or指令 根据ASCII码&#xff0c;字符的大写和小写相差一个0010 0000&#xff…

c++——入门(下)

6. 引用 6.1 引用概念 引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&#xff0c;编译器不会为引用变量开辟内存空 间&#xff0c;它和它引用的变量共用同一块内存空间。 类型& 引用变量名(对象名) 引用实体&#xff1b; void TestRef() {int a 1…

Linux基础IO【重定向及缓冲区理解】

✨个人主页&#xff1a; 北 海 &#x1f389;所属专栏&#xff1a; Linux学习之旅 &#x1f383;操作环境&#xff1a; CentOS 7.6 阿里云远程服务器 文章目录 &#x1f307;前言&#x1f3d9;️正文1、文件描述符1.1、先描述&#xff0c;再组织1.2、files_struct1.3、分配规则…

阿里云g8i服务器Intel Xeon(Sapphire Rapids) Platinum 8475B

阿里云服务器ECS通用型实例规格族g8i采用2.7 GHz主频的Intel Xeon(Sapphire Rapids) Platinum 8475B处理器&#xff0c;3.2 GHz睿频&#xff0c;g8i实例采用阿里云全新CIPU架构&#xff0c;可提供稳定的算力输出、更强劲的I/O引擎以及芯片级的安全加固。阿里云百科分享阿里云服…

【设计模式】策略模式

目录 一、定义二、结构三、优点四、缺点五、使用场景六、代码示例 一、定义 1.该模式定义了一系列算法&#xff0c;并将每个算法封装起来&#xff0c;使它们可以相互替换&#xff0c;且算法的变化不会影响使用算法的客户 2.策略模式属于对象行为模式&#xff0c;它通过对算法进…

Shell脚本2

自定义局部变量 :定义在一个脚本文件中的变量 只能在这个脚本文件中使用的变量&#xff0c;局部变量 语法&#xff1a; var_namevalue 变量定义规则 变量名称可以有字母,数字和下划线组成, 但是不能以数字开头 等号两侧不能有空格 在bash环境中, 变量的默认类型都是字符串…

二叉树(纲领篇)

文档阅读 文档阅读 二叉树解题的思维模式分两类&#xff1a; 1、是否可以通过遍历一遍二叉树得到答案&#xff1f;如果可以&#xff0c;用一个 traverse 函数配合外部变量来实现&#xff0c;这叫「遍历」的思维模式。 2、是否可以定义一个递归函数&#xff0c;通过子问题&a…

【pinia】新一代更好用的状态管理器Pinia

目录 一&#xff0c;Pinia状态管理库 1.Pinia介绍 2.Pinia的核心特性 3.核心概念 4.Pinia vs Vuex 5.Pinia & Vuex的不同 6.Pinia名字 二&#xff0c;Pinia基本使用 1.安装Pinia 2.配置main.ts文件 3.创建store/index.ts文件 4.使用数据 三&#xff0c;状态更新…