C++ 算术运算符 - 重载

算术运算符重载

算术运算符重载分为:+ , - , * , / , % , += , -= , *= , /= …

这篇文章主要以 加号运算符重载 为例子介绍,其他的重载方式都是一样的。


为什么要使用加号运算符重载(operator)

C/C++的运算符,仅限于基本数据类型的运算。

那么问题来了,怎么使一头牛和一只羊类型的数据相加呢?
一头牛 + 一头马 = ?(牛马神兽?)
一个圆 + 一个圆 = ? (想要变成一个更大的圆)
一头牛 – 一只羊 = ? (想要变成4只羊,原始的以物易物:1头牛价值5只羊)

解决方案:
使用运算符重载


运算符重载的两种形式

一、使用成员函数重载运算符
二、使用非成员函数【友元函数】重载运算符


使用operator关键字实现运算符重载

下面示例以 + 号作为例子
其他运算符 - * / 等都是一样的


使用成员函数重载运算符

需求:
使用运算符重载,来实现:
一头牛 + 一只羊 = ?
一头牛 + 一头牛 = ?

假设:
一斤猪肉 = 两斤牛肉
一斤猪肉 = 三斤羊肉

代码示例前讲解:
第一:定义一头牛的类,实现定义函数重载运算符
第二:定义羊类
第三:定义猪类
第四:main函数实现

代码实例:

第一:定义牛类Cow.h

#pragma once

class Sheep;
class Pig;

class Cow {
public:
	Cow(float weigth = 0.0);

	// 使用运算符重载,来实现:一头牛 + 一只羊 = ?
							// 一头牛 + 一头牛 = ?
	Pig operator+(const Sheep &sheep);	// 牛+羊
	Pig operator+(const Cow &cow);		// 牛+牛

private:
	float weigth;	// 牛的体重
};

Cow.cpp

#include "Cow.h"
#include "Pig.h"
#include "Sheep.h"

Cow::Cow(float weigth) {
	this->weigth = weigth;
}

Pig Cow::operator+(const Sheep &sheep) {
					// 牛肉 * 2	+	// 羊肉 * 3
	float ret = this->weigth * 2 + sheep.getWeigth() * 3;
	// 返回前转换为Pig类型
	return Pig(ret);
}

Pig Cow::operator+(const Cow &cow) {
					// (牛		+		牛)*	2
	float ret = (this->weigth + cow.weigth) * 2;
	// 返回前转换为Pig类型
	return Pig(ret);
}

第二:定义羊类Sheep.h

#pragma once 

class Sheep {
public:
	Sheep(float weigth = 0.0);

	float getWeigth() const;

private:
	float weigth; // 羊的体重
};

Sheep.cpp

#include "Sheep.h"

Sheep::Sheep(float weigth) {
	this->weigth = weigth;
}

float Sheep::getWeigth() const {
	return weigth;
}

第三:定义猪类Pig.h

#pragma once

#include <string>

class Pig {
public:
	Pig(float weigth = 0.0);

	std::string description() const;

private:
	float weigth;
};

Pig.cpp

#include <sstream>
#include "Pig.h"

Pig::Pig(float weigth) {
	this->weigth = weigth;
}

std::string Pig::description() const {
	std::stringstream ret;

	ret << "weigth = " << weigth << "斤猪肉" << std::endl;

	return ret.str();
}

第四:main函数实现

#include <iostream>
#include "Pig.h"
#include "Cow.h"
#include "Sheep.h"

using namespace std;

int main(void) {
	Cow c1(100);	// 定义一头牛一百斤
	Cow c2(200);	// 定义一头牛两百斤
	
	// 调用c1.operator+(c2);
	//相当于:Pig p = c1.operator+(c2);
	Pig p = c1 + c2;
	cout << p.description();

	Sheep s(100);	// 定义一只羊一百斤
	
	// 相当于: p = c1.operator+(s);
	p = c1 + s;
	cout << p.description();

	system("pause");
	return 0;
}

运行截图:
在这里插入图片描述


使用非成员函数【友元函数】重载运算符

和友元函数的定义的方法一样的
不知道友元函数的朋友,请看我另一篇文章:C++ 友元https://blog.csdn.net/cpp_learner/article/details/104193181

需求:
使用友元函数实现:
一头牛+一头牛
一头牛+一头羊
一头羊+一头牛
注意:牛+羊 和 羊+牛 是不一样的,会调用不一样的重载运算符函数

代码实例:

Cow.h

#pragma once

class Sheep;
class Pig;

class Cow {
public:
	Cow(float weigth = 0.0);

private:
	float weigth;	// 牛的体重

	// 声明为友元函数
	friend Pig operator+(Cow &c1, Cow &c2);
	friend Pig operator+(Cow &cow, Sheep &sheep);
	friend Pig operator+(Sheep &sheep, Cow &cow);
};

Cow.cpp

#include "Cow.h"
#include "Pig.h"
#include "Sheep.h"

Cow::Cow(float weigth) {
	this->weigth = weigth;
}

Sheep.h

#pragma once 

class Pig;
class Cow;

class Sheep {
public:
	Sheep(float weigth = 0.0);

	float getWeigth() const;

private:
	float weigth; // 羊的体重
	
	// 声明为友元函数
	friend Pig operator+(Cow &cow, Sheep &sheep);
	friend Pig operator+(Sheep &sheep, Cow &cow);
};

Sheep.cpp

#include "Sheep.h"

float Sheep::getWeigth() const {
	return weigth;
}

Pig.h

#pragma once

#include <string>

class Pig {
public:
	Pig(float weigth = 0.0);

	std::string description() const;

private:
	float weigth;
};

Pig.cpp

#include <sstream>
#include "Pig.h"

Pig::Pig(float weigth) {
	this->weigth = weigth;
}

std::string Pig::description() const {
	std::stringstream ret;

	ret << "weigth = " << weigth << "斤猪肉" << std::endl;

	return ret.str();
}

main函数实现

#include <iostream>
#include "Pig.h"
#include "Cow.h"
#include "Sheep.h"

using namespace std;

// 牛+牛
Pig operator+(Cow &c1, Cow &c2) {
	int ret = (c1.weigth + c2.weigth) * 2;
	return Pig(ret);
}

// 牛+羊
Pig operator+(Cow &cow, Sheep &sheep) {
	int ret = cow.weigth*2 + sheep.weigth*3;
	return Pig(ret);
}

// 羊+牛
Pig operator+(Sheep &sheep, Cow &cow) {
	int ret = sheep.weigth*3 + cow.weigth*2;
	return Pig(ret);
}

int main(void) {
	Cow c1(100);
	Cow c2(200);
	Pig p = c1 + c2;
	cout << p.description();

	Sheep s(100);
	p = s + c1;
	cout << p.description();

	system("pause");
	return 0;
}

运行截图:

在这里插入图片描述


两种方式的区别

区别:

  1. 使用成员函数来实现运算符重载时,少写一个参数,因为第一个参数就是this指针。

两种方式的选择:

  1. 一般情况下,单目运算符重载,使用成员函数进行重载更方便(不用写参数)
  2. 一般情况下,双目运算符重载,使用友元函数更直观
    方便实现a+b和b+a相同的效果,成员函数方式无法实现。
    例如: 100 + cow; 只能通过友元函数来实现
    cow +100; 友元函数和成员函数都可以实现

特殊情况:
(1) = () [ ] -> 不能重载为类的友元函数!!!(否则可能和C++的其他规则矛盾),只能使用成员函数形式进行重载。
(2)如果运算符的第一个操作数要求使用隐式类型转换,则必须为友元函数(成员函数方式的第一个参数是this指针)

注意:
同一个运算符重载, 不能同时使用两种方式来重载,会导致编译器不知道选择哪一个(二义性)


运算符重载的禁区和规则

  1. 为了防止对标准类型进行运算符重载,C++规定重载运算符的操作对象至少有一个不是标准类型,而是用户自定义的类型;
    比如不能重载 1+2
    但是可以重载 cow + 2 和 2 + cow // cow是自定义的对象

2.不能改变原运算符的语法规则, 比如不能把双目运算符重载为单目运算

  1. 不能改变原运算符的优先级

  2. 不能创建新的运算符,比如 operator**就是非法的, operator*是可以的

  3. 不能对以下这四种运算符,使用友元函数进行重载【 = 赋值运算符,()函数调用运算符,[ ]下标运算符,->通过指针访问类成员】

  4. 不能对禁止重载的运算符进行重载

不能被重载的运算符

******
成员函数.
域运算::
内存长度运算sizeof
三目运算? :
预处理#

可以被重载的运算符

******
双目运算符+ - * / %
关系运算符== != < <= > >=
逻辑运算符&&与 或 !非
单目运算符+(正号) -(负号) *(指针) &(取地址) ++ –
位运算& 或 ~ ^ <<(左移) >>(右移)
赋值运算符= += -= *= /= %= &= 或等 ^= <<= >>=
内存分配new delete new[ ] delete[ ]
其他( ) 函数调用 -> 成员访问 [ ]下标 ,逗号

注意:
表格中逻辑运算符中 “或” 是 ||
赋值运算符中 “或等” 是 |=


总结
算术运算符重载,也许用得不多,但也是一个挺有用的知识点。如果有需求是两个对象之间进行算术运算符操作,就可以使用到它!

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cpp_learners

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值