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

本文详细介绍了C++中运算符重载的概念、限制、优先级和应用实例,包括如何实现技能类对象之间的融合、增强与调整,以及不同运算符的正确使用方法。

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

 

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_; }	//默认构造函数,默认几率和伤害都为0
	void 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.2
	if (another.jilv > 100)another.jilv = 100;	//如果几率大于100,则为100
	another.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_; }	//默认构造函数,默认几率和伤害都为0
	void 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.2
	if (another.jilv > 100)another.jilv = 100;	//如果几率大于100,则为100
	another.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.
请按任意键继续. . .


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值