(一二二)运算符重载——第十一章

来源:互联网 发布:淘宝搜索的算法 编辑:程序博客网 时间:2024/05/21 19:41

本章重点是类设计技术,而不是通用原理。

 

C++的重点是多使用

正如我之前写了这么多的学习笔记一样,几乎绝大部分的代码,都是我根据书上的知识,然后理解自行再创造写下的。虽然遇见了不少问题,但解决后,下次再遇见这类情况,解决起来很轻松,绝大多数都可以直接靠记忆书写代码,即使个别忘记了,回头翻一番笔记,基本也能解决,需要靠百度去解决的,已经很少了。

 

 

运算符重载是一种形式的C++多态(就像函数重载那样,同名但调用不同的函数)。

 

要重载运算符,需要使用被称为运算符函数的特殊函数形式。运算符函数格式如下:

operator 运算符 (argument-list);

例如:operator +(); 表示重载加号运算符,而operator -()表示重载减号运算符。

其中,运算符必须是有效的C++运算符,而不是是自己捏造的(例如+-*/之类就是有效的,而@就是无效的)。

 

但需要注意的是,定义运算符有时需在类中定义(非必须,具体看下面的运算符重载的限制),对该类对象有效。运算符前面是的调用该方法的对象,参数中是被调用的对象。

例如:

class Mm{int a;public:...... ;Mm operator + (const Mm &bb){return this->a + bb.a;}}

这里实际上就是把+号运算符重载为对对象有用的加号运算符了。

 

如代码:


#include<iostream>#include<string>class Skill//技能类{std::string name;//技能名称double jilv;//几率double dam;//伤害public:Skill(std::string name_ = "无技能", double jilv_ = 0.0, double dam_ = 0.0) { name = name_;jilv = jilv_;dam = dam_; }//默认构造函数,默认几率和伤害都为0void show();Skill operator +(const Skill&b);//技能融合函数,将2个技能融合起来变成第三个技能};int main(){using namespace std;Skill one("拔刀斩", 20, 500);Skill two("半月斩", 15, 400);one.show();two.show();Skill three = one + two;//新对象为两个对象之和cout << "技能已融合!新技能get!" << endl;three.show();system("pause");return 0;}void Skill::show(){std::cout << "技能:" << name << " 的发动几率为 " << jilv << " %,伤害为: " << dam << " 点。" << std::endl;}Skill Skill::operator+(const Skill&b){Skill another;another.name = name;//名字延续加号前的another.jilv = (jilv + b.jilv)*1.25;//几率为两个几率之和,乘以1.2if (another.jilv > 100)another.jilv = 100;//如果几率大于100,则为100another.dam = dam + b.dam*0.5;//伤害为第一个伤害加上第二个伤害的一半return another;//返回对象(不是引用)}

输出:


技能:拔刀斩 的发动几率为 20 %,伤害为: 500 点。技能:半月斩 的发动几率为 15 %,伤害为: 400 点。技能已融合!新技能get!技能:拔刀斩 的发动几率为 43.75 %,伤害为: 700 点。请按任意键继续. . .

总结:

①运算符重载的关键,是运算符左边的调用重载函数,右边的作为参数,所以在码代码的时候,需要注意顺序。

例如,one+two时,按照类方法,新对象threeone的名字,如果是two+one,新对象threetwo的名字。

当然,具体是什么,根据函数定义来决定。

 

 

 

 

运算符重载的限制:

多数C++运算符(参见表11.1,如下图,不过看不清……)都可以用这样的方式重载。

ps:图看不清,不传了。具体请看书(最好看实体书,pdf版不是很清楚,不过大部分都可以重载)


但也有一些限制,例如:重载的运算符不必是成员函数,但必须至少有一个操作数是用户定义的类型

 

具体限制如下:

①重载后的运算符,必须至少有一个操作数是用户定义的类型(否则不知道你使用的是运算符重载,在运算符重载的函数定义里,也容易出问题),这将防止用户为标准类型重载运算符。

因此,不能把减法运算符重载为2个标准类型(如int或者double)的值的和,而不是他们的差。

 

②使用运算符时不能违反运算符原来的句法规则。例如,+-*/以及%这五种运算符,需要两个数来参与。你不能只给他用一个数。例如a+b是可以的,但是+a这种是不行的。而像地址运算符&就是只对一个数使用,如&dizhi

 

另外,运算符即使被重载,其运算优先级也与原来的运算符的优先级相同,例如a+b/c,即使对+进行运算符重载,也依然是先计算b/c,再计算a+ (b/c)的结果。

 

③不能创建新的运算符,只能用已有的

 

④不能重载下面的运算符。

1sizeof   sizeof运算符

2.  ←这是一个句号,成员运算符,比如结构名.结构内变量

3.*    ←句号和乘号,成员指针运算符(没见过)

4:: ←两个冒号,作用域解析运算符

5?: 条件运算符,比如: a>b?c:d

6typeid ←一个RTTI运算符(没见过)

7const_cast ←强制类型转换运算符(没见过这种用法)

8dynamic_cast ←强制类型转换运算符(没见过这种用法)

9reinterpret_cast ←强制类型转换运算符(没见过这种用法)

10static_cast ←强制类型转换运算符(没见过这种用法)

而上面那个图片中的运算符,基本都可以用(反正大部分都能用,不能用的是少数)。

 

⑤大部分运算符:可以通过成员、非成员函数进行重载;

以下几个运算符,只能通过成员函数进行重载:

1= ←赋值运算符

2() ←函数调用运算符

3[] ←下标运算符(为什么叫下标?

4-> ←通过指针访问类成员的运算符(不懂,是指this->私有成员这样么?

 

 

⑥运算符重载最好遵循一般逻辑,例如不要把加法运算符(+)重载为两个对象各个值的差这种违反直觉的事情。

 

⑦重载运算符面对不同对象时,需要定义不同类型的重载运算符函数。

例如,一个对象 另一个对象,和一个对象 一个int/double值,是不能使用同一个函数的。

 

如代码:

#include<iostream>#include<string>class Skill//技能类{std::string name;//技能名称double jilv;//几率double dam;//伤害public:Skill(std::string name_ = "无技能", double jilv_ = 0.0, double dam_ = 0.0) { name = name_;jilv = jilv_;dam = dam_; }//默认构造函数,默认几率和伤害都为0void show()const;Skill operator +(const Skill&b)const;//技能融合函数,将2个技能融合起来变成第三个技能void operator*=(const double &b);//技能增强函数,重载运算符*=void operator/=(const double &b);//另一种形式的增强,通过降低概率增加伤害,重载运算符/=};int main(){using namespace std;Skill one("拔刀斩", 20, 500);Skill two("半月斩", 15, 400);one.show();two.show();Skill three = one + two;//新对象为两个对象之和cout << "技能已融合!新技能get!" << endl;three.show();cout << "现将增强你的技能,增强发动几率和伤害,增加比例为1.5。" << endl;three *= 1.5;//重载*=运算符three.show();cout << "现在将降低概率,增强伤害,系数为:2" << endl;three /= 2;//重载/=运算符three.show();cout << "bye." << endl;system("pause");return 0;}void Skill::show()const{std::cout << "技能:" << name << " 的发动几率为 " << jilv << " %,伤害为: " << dam << " 点。" << std::endl;}Skill Skill::operator+(const Skill&b)const{Skill another;another.name = name;//名字延续加号前的another.jilv = (jilv + b.jilv)*1.25;//几率为两个几率之和,乘以1.2if (another.jilv > 100)another.jilv = 100;//如果几率大于100,则为100another.dam = dam + b.dam*0.5;//伤害为第一个伤害加上第二个伤害的一半return another;//返回对象(不是引用)}void Skill::operator*=(const double &b){jilv *= b;//几率和伤害都乘以系数dam *= b;}void Skill::operator/=(const double &b){jilv /= b;//几率除系数dam *= b;//伤害乘系数}

输出:


技能:拔刀斩 的发动几率为 20 %,伤害为: 500 点。技能:半月斩 的发动几率为 15 %,伤害为: 400 点。技能已融合!新技能get!技能:拔刀斩 的发动几率为 43.75 %,伤害为: 700 点。现将增强你的技能,增强发动几率和伤害,增加比例为1.5。技能:拔刀斩 的发动几率为 65.625 %,伤害为: 1050 点。现在将降低概率,增强伤害,系数为:2技能:拔刀斩 的发动几率为 32.8125 %,伤害为: 2100 点。bye.请按任意键继续. . .


0 0
原创粉丝点击