运算符重载

运算符重载是一种形式的c++多态,上一张笔记的函数重载也可以叫做函数多态,运算符重载将重载的概念扩展到运算符上,允许C++运算符有多种含义。很多C++运算符已经被重载,例如 将解引用符号*,但他用于数值之间就是乘积,C++根据操作数的数目和类型来决定采用哪种操作。
C++允许将运算符重载扩展到我们自己定义的类型,例如可以让两个对象相加,编译器根据操作数的数目和类型决定使用哪种加法定义。
例:

#include<iostream>
int main()
{
	int a[10];
	int b[10] = {1,2,3,4,5,6,7,8,9,10};
	int c[10] = { 11,12,13,14,15,16,17,18,19,20 };
	for (size_t i = 0; i < 20; i++)
	{
		a[i] = b[i] + c[i];
	}
}

也可以重载加法运算符,并用表示数组的类相加,
如 c = a + b
要重载运算符,需使用被称为运算符函数的特殊函数形式,operatorop(argument-list)
例如 operator+()表示重载+运算符, operator*()表示重载*运算符,op必须是有效的C++运算符,斌是虚构的符号 如@等。
operator[]()重载[]运算符,因为[]是数组索引运算符
如果有一个类,重载了+运算符,使得数据求和可以通过对象直接相加 比如

#include<iostream>
class Salesperson
{
public:
	Salesperson(int n = 5);
	Salesperson()
	{
		sale = 0;
	}
	int operator +(const Salesperson&t);
private:
	int sale;
};


Salesperson::Salesperson(int n)
{
	sale = n;
}

int Salesperson::operator+(const Salesperson& t)
{
	int sale = this->sale + t.sale;
	return sale;
}
int main()
{
	using std::cout;
	using std::endl;
	Salesperson s1(10);
	Salesperson s2(20);
	int ret = s1 + s2;
	cout << ret << endl;
}

结果是30 因为编译器发现是类对象,符合我们重载函数的特征标,因此重载运算符函数就变成了 sale = s1.operator+(s2) 显式地调用s2对象,可以简单地使用运算符表示。
然后我们会再通过一些例子深入了解运算符重载以及一些限制

计算时间(运算重载示例)

例子来源C++ Primer Plus(第6版)可以到我的资源站下载哦!

image.png
书上的翻译太拗口了,我直接改编一下,我早上花了2个小时40分钟用来健身,下午花费了2小时35分健身,猛男嘛!理解一下。如果我们想知道花了多少时间,加法是最合适的,但问题是他们的类型也不同,我们将使用Time类进行计算。

#pragma once
#include<iostream>
class Time
{
public:
	Time();
	~Time();
	Time(int h, int m = 0);
	void AddMin(int m);
	void Addhour(int h);
	void reset(int h = 0, int m = 0);
	Time Sum(const Time& T)const;
	void show()const;
private:
	int hours;
	int minutes;

};

#include "Time.h"

Time::Time()
{
	hours = minutes = 0;
}

Time::~Time()
{
}

Time::Time(int h, int m)
{
	hours = h;
	minutes = m;
}

void Time::AddMin(int m)
{
	minutes += m;
	hours += minutes / 60;
	minutes %= 60;
}

void Time::Addhour(int h)
{
	hours += h;
}

void Time::reset(int h, int m)
{
	hours = h;
	minutes = m;
}

Time Time::Sum(const Time& T) const
{
	Time sum;
	sum.minutes = minutes + T.minutes;
	sum.hours = hours + T.hours + sum.minutes / 60;
	sum.minutes %= 60;
	return sum;
}

void Time::show() const
{
	std::cout << hours << " hours," << minutes << " minutes";
}

#include"Time.h"
int main()
{
	using std::cout;
	using std::endl;
	Time planning;
	Time p1(2, 40);
	Time p2(5, 55);
	Time total;
	cout << "planning time = ";
	planning.show();
	cout << endl;
	cout << "p1 time = ";
	p1.show();
	cout << endl;
	cout << "p2 time = ";
	p2.show();
	cout << endl;
	total = p1.Sum(p2);
	cout << "p1.sum(p2) = ";
	total.show();
	cout << endl;
	return 0;
}

首先看一下算法,满60分钟是一小时 所以minutes/60就是分钟的小时 而minutes%=60 是模运算,为了计算分钟数
注意函数返回值不可以是引用,因为引用就是sunm,sum在函数执行完成之后就被销毁了,而如果返回Time,则回调用默认构造函数 调用函数将得到它的拷贝( 当用一个对象去初始化同类的另一个对象时,会引发复制构造函数被调用。例如,下面的两条语句都会引发复制构造函数的调用,用以初始化 total)

添加加法运算符

修改我们之前写的成员函数sum改为重载加法运算符

#pragma once
#include<iostream>
class Time
{
public:
	Time();
	Time(int h, int m = 0);
	void AddMin(int m);
	void Addhour(int h);
	void reset(int h = 0, int m = 0);
	Time operator+(const Time& T)const;
	void show()const;
private:
	int hours;
	int minutes;
};

此时operator+()也是由Time对象调用的,因此可以

total = p1.operator+(p2);
也可以用
total = p1+p2;

然后我们修改main.cpp文件然后调用它

#include"Time.h"
int main()
{
	using std::cout;
	using std::endl;
	Time planning;
	Time p1(2, 40);
	Time p2(5, 55);
	Time total;
	cout << "planning time = ";
	planning.show();
	cout << endl;
	cout << "p1 time = ";
	p1.show();
	cout << endl;
	cout << "p2 time = ";
	p2.show();
	cout << endl;
	total = p1 + p2;
	cout << "p1.sum(p2) = ";
	total.show();
	cout << endl;
	Time moren(3,28);
	cout << "moren time = ";
	moren.show();
	cout << endl;
	cout << "total.operator+(morn) = ";
	total = total.operator+(moren);
	 total.show();
	cout << endl;
	return 0;
}

Time A,B,C
A+B+C这样做合法吗
image.png
转换一下函数表示法:A.operator+(B.operator+(C));

重载限制

多数C++运算符都可以用这样的方式重载,重载运算符不必是成员函数,但必须至少有一个是用户定义的类型。

  1. 至少有一个操作数是用户自定义类型,防止重载标准类型的运算符
  2. 使用运算符不能违反运算符原来的句法规则。例如,不能将2求模运算符重载为使用一个操作数 ,同样也不能修改运算符的优先级,比如重载加号 重载后优先级和加号优先级一样
  3. 不能创建新运算符
  4. 不能重载以下列举的运算符
    sizeof . .* :: ? typeid const_cast dynamic_cast reinterpret_cast static_cast
    5.下面将列举的是只能通过成员函数重载的运算符
    = () [] ->
    下表是既可以通过成员函数也可以通过非成员函数重载的运算符
    image.png

重载其他运算符

  • 两个时间可能相减
  • 时间乘以一个因子
    修改后的Time.h
#pragma once
#include<iostream>
class Time
{
public:
	Time();
	Time(int h, int m = 0);
	void AddMin(int m);
	void Addhour(int h);
	void reset(int h = 0, int m = 0);
	Time operator+(const Time& T)const;
	Time operator-(const Time & T)const;
	Time operator*(double n)const;
	void show()const;
private:
	int hours;
	int minutes;

};

这里仅就新重载的两条代码进行代码定义
Time Time::operator*(double n) const
{
	Time res;
	long totalminutes = hours * n * 60 + minutes * n;
	res.hours = totalminutes / 60;
	res.minutes = totalminutes % 60;
	return res;
}
Time Time::operator-(const Time& T) const
{
	Time sum;
	int t1, t2;
	t1 = minutes + 60 * hours;
	t2 = T.minutes + 60 * T.hours;
	sum.hours = (t1 - t2) / 60;
	sum.minutes = (t1 - t2) % 60;
	return sum;
}

然后就可以修改main.cpp

#include"Time.h"
int main()
{
	using std::cout;
	using std::endl;
	Time planning;
	Time p1(4, 35);
	Time p2(2, 47);
	Time total;
	cout << "planning time = ";
	planning.show();
	cout << endl;
	cout << "p1 time = ";
	p1.show();
	cout << endl;
	cout << "p2 time = ";
	p2.show();
	cout << endl;
	total = p1 + p2;
	cout << "p1.sum(p2) = ";
	total.show();
	cout << endl;
	Time moren(3,28);
	cout << "moren time = ";
	moren.show();
	cout << endl;
	cout << "total.operator+(morn) = ";
	total = total.operator+(moren);
	 total.show();
	cout << endl;
	cout << "moren + p1 + p2 = ";
	total = moren + p1 + p2;
	total.show();
	cout << endl;
	cout << "p1-p2 = ";
	total = p1 - p2;
	total.show();
	cout << endl;
	cout << "p1*1.5 = ";
	total = p1 * 1.5;
	total.show();
	return 0;
}

运行截图

image.png

网站标题:CV鼻祖洋芋

原创文章,作者:locus,如若转载,请注明出处:https://blog.cvpotato.cn/forward-code/c/218/

本博客所发布的内容,部分为原创文章,转载注明来源,网络转载文章如有侵权请联系站长!

(0)
上一篇 6天前
下一篇 6天前

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注