运算符重载

本文详细介绍了C++中的运算符重载,包括成员函数和友元函数的重载方式,以及自增自减、流提取运算符的重载规则。并展示了如何通过运算符重载实现一个向量类Vec2D,包含加减、自增自减、索引访问等操作,并提供了相应的代码示例。
摘要由CSDN通过智能技术生成

运算符重载的特点

可以将运算符实际就是函数,运算符重载实际就是函数重载,运算符重载有两种形式:重载为类的成员函数,重载为类的非成员函数(一般为友元)。

重载为类的成员函数时,函数的参数个数比原来的操作数要少一个

(this作为一个成员,另一个对象作为另一个成员)
1、双目运算符重载为类的成员函数时,函数只显示说明一个参数,该形参是运算符的右操作数。(a+b)
2、前置单目运算符重载为类的成员函数时,不需要显示说明参数,即该函数没有形参。(++a)
3、后置单目运算符重载为类的成员函数时,函数要带有一个整形形参。(a++)
在这里插入图片描述

重载为类的非成员函数时,函数的参数个数一般为两个

成员函数运算符与友元函数运算符的异同

  • 一般情况下,单目运算符最好重载为类的成员函数;双目运算符最好重载为类的友元函数
  • 若运算符所需的操作数希望有隐式类型转换,则只能选择友元函数。
  • 当运算符函数是一个成员函数时,最左边的操作数必须是运算符类的一个类对象。

不可重载的运算符

. 类属关系运算符
.* 成员指针运算符
:: 作用域运算符
? : 条件运算符
#:编译预处理符号
sizeof() 取数据类型的长度

左值Lvalue与右值Rvalue

左值:能出现在赋值运算符“=”的左边,能被赋值
右值:出现在赋值运算符“=”的右边,不能被赋值
是不是尽量都重载为一个左值?
例:重载r1[i];

double& Vec2D::operator[](const int index)
{
	if (index == 0)return x;
	else if (index == 1)return y;
	else cout << "检索超过范围" << endl;
}

在double后面加一个&,就表示重载为左值,此时可以进行赋值。

重载自增自减运算符

PS:C语言里头,前自增和后自增都是一个右值,在C++里头看你怎么重载的自增运算符!

前置与后置的区别

前置重载无参数,返回引用类型。
后置重载带参数,一般使用一个int来区别,但是不参与运算。
在这里插入图片描述

重载流提取运算符(<<,>>)

只能重载为友元函数
原因如下:使用<<和>>运算符时,第一个参数是流类的实例:cout<<x<<y;但是如果重载为类成员函数,当调用该运算符后,左操作数必须是该类的实例,形式为 r1<<cout;不符合使用习惯,因此只能重载为友元

istream& operator>>(istream& steam, Vec2D& v1)
{
	// TODO: 在此处插入 return 语句
	steam >> v1[0] >> v1[1];
	return steam;
}

代码示例

通过运算符重载实现一个向量类Vec2D,可以使以下测试代码编译通过。
#include <iostream>
#include "Vec2D.h"
using std::cout;
using std::endl;

int main() {
	// 创建向量对象
	Vec2D v1{ 3,5 }, v2{ 4,6 };

// 向量转为字符串
cout << "v1 = " << v1.toString() << endl;
cout << "v2 = " << v2.toString() << endl;
// 向量加法: 向量+向量,向量+数
Vec2D v3 = v1 + v2;
Vec2D v4 = v3 + 10.0;
cout << "v3 = " << v3.toString() << endl;
cout << "v4 = " << v4.toString() << endl;
// 向量减法,向量点积,向量数乘
Vec2D v5 = v2 - v1;
double v6 = v2 * v1;
Vec2D v7 = 2.1 * v3;
cout << "v2 - v1 = " << v5.toString() << endl;
cout << "v2 . v1 = " << v6 << endl;
cout << "v3 * 2.1 = " << (v3 * 2.1).toString() << endl;
cout << "2.1 * v3 = " << v7.toString() << endl;

Vec2D va1{ 10, 12 }, va2{ 1, 2 };
cout << " va1 += va2 : " << (va1 += va2).toString() << endl;
cout << " va1 -= va2 : " << (va1 -= va2).toString() << endl;
// 向量求负值
Vec2D v8 = v2.negative();
cout << "-v2 = " << (-v2).toString() << endl;
// 向量自增/自减
cout << "++v8 = " << (++v8).toString() << endl;
cout << "v8++ = " << (v8++).toString() << endl;
cout << "v8 = " << v8.toString() << endl;
cout << "--v2 = " << (--v2).toString() << endl;
// 读取或者修改向量元素
v1[0] = 31.1;
cout << "v1.x_ = " << v1[0] << endl;
cout << "v1.y_ = " << v1[1] << endl;
// v1[ 8 ] = 10.0;
// 向量的长度magnitude 和角度direction
cout << "v1.magnitude = " << v1.magnitude() << endl;
cout << "double(v1) = " << static_cast<double>(v1) << endl;
cout << "v1.direction = " << v1.direction() << endl;
// 比较两个向量
cout << "v1 compare v2 : " << v1.compareTo(v2) << endl;
cout << "Please input a Vec2D:";
Vec2D v9{};
std::cin >> v9; // operator>>(std::cin, v9);
cout << v9 << endl;
}

完整代码:

#define M_PI       3.14159265358979323846

#include <iostream>
#include <string>


using namespace std;

class Vec2D
{
private:
	double x = 0.000000;
	double y = 0.000000;
public:
	Vec2D(int a, int b)
		:x(a), y(b)
	{}
	Vec2D() {}
	string toString();

	//向量加法: 向量 + 向量,向量 + 数
	Vec2D operator+(const Vec2D& v1);
	Vec2D operator+(const double& a);

	// 向量减法,向量点积,向量数乘
	Vec2D operator-(const Vec2D& v1);
	double operator*(const Vec2D& v1);
	friend Vec2D& operator*(const double& a, Vec2D& v1);
	friend Vec2D operator*(Vec2D& v1, const double& a);

	//+=  -=
	Vec2D& operator+=(const Vec2D& v1);
	Vec2D& operator-=(const Vec2D& v1);

	// 向量求负值
	Vec2D negative();
	Vec2D operator-();

	// 向量自增/自减
	Vec2D& operator++();
	Vec2D& operator--();
	Vec2D operator++(int dummy);

	// 读取或者修改向量元素
	double& operator[](const int index);

	// 向量的长度magnitude 和角度direction
	double magnitude();
	explicit operator double()
	{
		return sqrt(x * x + y * y);
	}
	double direction();

	// 比较两个向量
	bool compareTo(Vec2D& v1);

	//重载>>和<<
	friend ostream& operator<<(ostream& steam, Vec2D& v1);
	friend istream& operator>>(istream& steam, Vec2D& v1);

};

int main()
{
	// 创建向量对象
	Vec2D v1{ 3,5 }, v2{ 4,6 };

	// 向量转为字符串
	cout << "v1 = " << v1.toString() << endl;
	cout << "v2 = " << v2.toString() << endl;
	// 向量加法: 向量+向量,向量+数
	Vec2D v3 = v1 + v2;
	Vec2D v4 = v3 + 10.0;
	cout << "v3 = " << v3.toString() << endl;
	cout << "v4 = " << v4.toString() << endl;
	// 向量减法,向量点积,向量数乘
	Vec2D v5 = v2 - v1;
	double v6 = v2 * v1;
	Vec2D v7 = 2.1 * v3;
	cout << "v2 - v1 = " << v5.toString() << endl;
	cout << "v2 . v1 = " << v6 << endl;
	cout << "v3 * 2.1 = " << (v3 * 2.1).toString() << endl;//设计成一个右值,不可赋值
	cout << "2.1 * v3 = " << v7.toString() << endl;

	Vec2D va1{ 10, 12 }, va2{ 1, 2 };
	cout << " va1 += va2 : " << (va1 += va2).toString() << endl;
	cout << " va1 -= va2 : " << (va1 -= va2).toString() << endl;
	// 向量求负值
	Vec2D v8 = v2.negative();
	cout << "-v2 = " << (-v2).toString() << endl;
	// 向量自增/自减
	cout << "++v8 = " << (++v8).toString() << endl;
	cout << "v8++ = " << (v8++).toString() << endl; //这条语句执行完了之后再执行++操作
	cout << "v8 = " << v8.toString() << endl;
	cout << "--v2 = " << (--v2).toString() << endl;
	// 读取或者修改向量元素
	v1[0] = 31.1;
	cout << "v1.x_ = " << v1[0] << endl;
	cout << "v1.y_ = " << v1[1] << endl;
	// v1[ 8 ] = 10.0;
	// 向量的长度magnitude 和角度direction
	cout << "v1.magnitude = " << v1.magnitude() << endl;
	cout << "double(v1) = " << static_cast<double>(v1) << endl;
	cout << "v1.direction = " << v1.direction() << endl;

	// 比较两个向量
	cout << "v1 compare v2 : " << v1.compareTo(v2) << endl;
	cout << "Please input a Vec2D:";
	Vec2D v9{};
	std::cin >> v9; // operator>>(std::cin, v9);
	cout << v9 << endl;

	return 0;
}

string Vec2D::toString()
{
	string tmp;
	tmp = "(" + to_string(x) + "," + to_string(y) + ")";
	return tmp;
}

Vec2D Vec2D::operator+(const Vec2D& v1)
{
	Vec2D v3{ 0,0 };
	v3.x = this->x + v1.x;
	v3.y = this->y + v1.y;
	return v3;
}

Vec2D Vec2D::operator+(const double& a)
{
	Vec2D v4{ 0,0 };
	v4.x = this->x + a;
	v4.y = this->y + a;
	return v4;
}

Vec2D Vec2D::operator-(const Vec2D& v1)
{
	Vec2D v5{ 0,0 };
	v5.x = this->x - v1.x;
	v5.y = this->y - v1.y;
	return v5;
}

double Vec2D::operator*(const Vec2D& v1)
{
	return x * v1.x + y * v1.y;
}

Vec2D& operator*(const double& a, Vec2D& v1)
{
	Vec2D tmp(0, 0);
	tmp.x = a * v1.x;
	tmp.y = a * v1.y;
	return tmp;
}

Vec2D operator*(Vec2D& v1, const double& a)
{
	Vec2D tmp(0, 0);
	tmp.x = v1.x * a;
	tmp.y = v1.y * a;
	return tmp;
}


Vec2D& Vec2D::operator+=(const Vec2D& v1)
{
	x = this->x + v1.x;
	y = this->y + v1.y;
	return *this;
}

Vec2D& Vec2D::operator-=(const Vec2D& v1)
{

	x = this->x - v1.x;
	y = this->y - v1.y;
	return *this;
}

Vec2D Vec2D::negative()
{
	Vec2D tmp(0, 0);
	tmp.x = -x;
	tmp.y = -y;
	return tmp;
}

Vec2D Vec2D::operator-()
{
	Vec2D tmp(0, 0);
	tmp.x = -x;
	tmp.y = -y;
	return tmp;
}

Vec2D& Vec2D::operator++()
{
	x++;
	y++;
	return *this;
}

Vec2D& Vec2D::operator--()
{
	x--;
	y--;
	return *this;
}

Vec2D Vec2D::operator++(int dummy)
{
	Vec2D tmp(0, 0);
	//先把值给赋了,然后在执行本对象的自增操作
	tmp.x = x;
	tmp.y = y;
	x++;
	y++;
	//返回临时对象
	return tmp;
}


//能被赋值,肯定是一个左值,可引用
double& Vec2D::operator[](const int index)
{
	if (index == 0)return x;
	else if (index == 1)return y;
	else cout << "检索超过范围" << endl;
}

double Vec2D::magnitude()
{
	return sqrt(x * x + y * y);
}

double Vec2D::direction()
{
	double tmp = y / (this->magnitude());
	tmp = asin(tmp);
	return tmp;
}

bool Vec2D::compareTo(Vec2D& v1)
{
	if (this->magnitude() > v1.magnitude())return true;
	return false;
}

ostream& operator<<(ostream& steam, Vec2D& v1)
{
	// TODO: 在此处插入 return 语句
	steam << "(" << v1[0] << "," << v1[1] << ")";
	return steam;
}

istream& operator>>(istream& steam, Vec2D& v1)
{
	// TODO: 在此处插入 return 语句
	steam >> v1[0] >> v1[1];
	return steam;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值