万物可运算——运算符重载(二)

为什么要使用运算符重载

C/C++的运算符,支持的数据类型,仅限于基本数据类型。
那么类与类之间可以进行加减乘除等运算吗?
一般来说C++是做不到的,但是我们可以通过运算符重载来实现这个功能。

运算符重载的基本用法:
①使用成员函数重载运算符
②使用非成员函数【友元函数】重载运算符

方式1:使用成员函数重载运算符

Cow.h

//需求:
// 规则:
// 一斤牛肉:2斤猪肉
// 一斤羊肉:3斤猪肉

#pragma once

class Pork;
class Goat;

class Cow
{
public:
	Cow(int weight);

	// 参数此时定义为引用类型,更合适,避免拷贝
	Pork operator+(const Cow& cow);  //同类型进行运算,很频繁

	Pork operator+(const Goat& goat); //不同类型进行运算,比较少见
private:
	int weight = 0;
};

Cow.h

#pragma once

class Pork;
class Goat;

class Cow
{
public:
	Cow(int weight);

	// 参数此时定义为引用类型,更合适,避免拷贝
	Pork operator+(const Cow& cow);  //同类型进行运算,很频繁

	Pork operator+(const Goat& goat); //不同类型进行运算,比较少见
private:
	int weight = 0;
};

Cow.cpp

#include "Cow.h"
#include "Pork.h"
#include "Goat.h"

Cow::Cow(int weight)
{
	this->weight = weight;
}


// 规则:
// 一斤牛肉:2斤猪肉
// 一斤羊肉:3斤猪肉
Pork Cow::operator+(const Cow &cow)
{
	int tmp = (this->weight + cow.weight) * 2;
	return Pork(tmp);
}

Pork Cow::operator+(const Goat& goat)
{
	// 不能直接访问goat.weight
	//int tmp = this->weight * 2 + goat.weight * 3;
	int tmp = this->weight * 2 + goat.getWeight() * 3;
	return Pork(tmp);
}

Goat.h

#pragma once
class Goat
{
public:
	Goat(int weight);
	int getWeight(void) const;
private:
	int weight = 0;
};

Goat.cpp

#include "Goat.h"

Goat::Goat(int weight) {
	this->weight = weight;
}

int Goat::getWeight(void) const
{
	return weight;
}

Pork.h

#pragma once
#include <iostream>

class Pork
{
public:
	Pork(int weight);
	std::string  description(void);

private:
	int weight = 0;
};

Pork.cpp

#pragma once
#include <iostream>

class Pork
{
public:
	Pork(int weight);
	std::string  description(void);

private:
	int weight = 0;
};

Pork.cpp

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

Pork::Pork(int weight)
{
	this->weight = weight;
}

std::string Pork::description(void)
{
	std::stringstream ret;
	ret << weight << "斤猪肉";
	return ret.str();
}

main.cpp

#include <iostream>
#include "Pork.h"
#include "Cow.h"
#include "Goat.h"

int main(void) {
	Cow c1(100);
	Cow c2(200);

	// 调用c1.operator+(c2);
	//相当于:Pork p = c1.operator+(c2);
	Pork p = c1 + c2;
	std::cout << p.description() << std::endl;

	Goat g1(100);
	p = c1 + g1;
	std::cout << p.description() << std::endl;
	
	system("pause");
	return 0;
}


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

Cow.h

#pragma once

class Pork;
class Goat;

class Cow
{
public:
	Cow(int weight);

	// 有友元函数实现运算符重载
	friend Pork operator+(const Cow& cow1, const Cow& cow2);
	friend Pork operator+(const Cow& cow1, const Goat& goat);
private:
	int weight = 0;
};

main.cpp

#include <iostream>
#include "Pork.h"
#include "Cow.h"
#include "Goat.h"

Pork operator+(const Cow &cow1, const Cow &cow2)
{
	int tmp = (cow1.weight + cow2.weight) * 2;
	return Pork(tmp);
}

Pork operator+(const Cow& cow1, const Goat& goat)
{
	int tmp = cow1.weight * 2 + goat.getWeight() * 3;
	return Pork(tmp);
}

int main(void) {
	Cow c1(100);
	Cow c2(200);
	Goat g1(100);

	Pork p = c1 + c2;
	std::cout << p.description() << std::endl;

	p = c1 + g1;  // 思考:如何实现:p = g1 + c1;
	std::cout << p.description() << std::endl;

	system("pause");
	return 0;
}

其他文件不变。

两种方式的区别:
使用成员函数来实现运算符重载时,少写一个参数,因为第一个参数就是this指针。


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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值