C++运算符重载(详解)

☘️ 前言:

⛪️ 个人主页:Jemery-An
🌈 个人介绍:业余编码,若有不对希望大家不吝赐教,相互学习,共同讨论,一起进步💪💓
☀️ 摘抄好句: 追光的人,他终将会光芒万丈
📑 文章介绍: 本文讲解了运算符重载基本使用方法与概念,希望阅读的人能有所收获吧!

一、运算符重载概念

一、官方解释:运算符重载将重载的概念扩展到运算符上,允许赋予C++运算符多种含义

二、平时我们 简单的 +,-,*,/,||,&&,!这类运算符只能用于对基本数据类型的运算,但是不能用于 类对象之间运算

那我们想要实现两个对象之间运算呢?比如相加两个对象

三、C++提供了运算符重载机制,通过重载运算符,赋予其运算符另一种功能,不再局限于基本数据类型的运算,所以就能实现两个对象相加这样的需求

四、运算符重载其目的就是为了让运算符也能操作类对象

二、运算符重载语法

要重载运算符,需使用被称为运算符函数的特殊函数形式。运算符函数的格式如下

返回值类型 operator 运算符(agrgument-list)
{
.....
}

例如:
obj operator +();  //重载的是+运算符
obj operator -();  //重载的是-运算符

运算符必须是有效的C++运算符,不能虚构一个新的运算符。例如不能有operator @();这样的函数运算符,因为C++中没有这样的运算符

三、运算符重载实例

、如果我们想对两个人的数学成绩英语成绩进行相加,其就是为了实现:P3=P1+P2
不使用重载运算符:我们可以通过自己写成员函数或定义全局函数的方式来实现两个对象相加属性后返回新对象
代码如下:

#include<iostream>
using namespace std;
class Person {
public:
	Person() {
	
	};
	Person(int a, int b) {
		this->math = a;
		this->eng = b;
	}

	Person sum(Person& p1) {//成员函数
		Person temp;
		temp.eng = this->eng + p1.eng;
		temp.math = this->math + p1.math;
		return temp;
	}
public:
	int math=0, eng=0;
};

Person sum(Person& p1,Person& p2) {		//全局函数
	Person temp;
	temp.eng = p2.eng + p1.eng;
	temp.math =p2.math + p1.math;
	return temp;
}

int main() {
	Person p1(90, 98);
	Person p2(100, 90);
	Person p3;
	//p3 = p1.sum(p2); 局部函数
	p3 = sum(p1, p2);	
	cout << p3.eng << endl << p3.math << endl;
	return 0;
}

🍎小知识1: 参数为引用类型的好处

来看sum函数不管是成员函数还是全局函数,注意参数都是引用,但返回类型却不是引用。将参数作为引用的目的是为了提高效率。
如果按值传递Person对象,代码的功能将相同,但传递引用,速度将更快,使用的内存将更少,在编码过程中我们要巧妙的使用引用!

🍎小知识2:为什么返回类型不能用引用

如果返回类型为Person & 引用的则是temp对象,由于temp对象是局部对象在函数结束时将被删除,因此,引用将指向一个不存在的对象。
如果使用返回类型Person就意味着在删除sum之前构造它的拷贝,调用函数将得到该拷贝。

使用重载运算符:
运算符可以被重载为成员函数,也可以被重载为全局函数,我们一般倾向于把运算符函数定义为成员函数,这样能清晰的看出与类的关系
代码如下:

#include<iostream>
using namespace std;
class Person {
public:
	Person() {
	
	};
	Person(int a, int b) {
		this->math = a;
		this->eng = b;
	}

	Person operator+(Person& p1) {  //成员函数
		Person temp;
		temp.eng = this->eng + p1.eng;
		temp.math = this->math + p1.math;
		return temp;
	}
public:
	int math,eng;
};

Person operator+(Person & p1, Person & p2) {    //全局函数 
	Person temp;
	temp.eng = p2.eng + p1.eng;
	temp.math =p2.math + p1.math;		
	return temp;	
}					对于一个类的运算,相同运算符重载的函数,全局和成员只能存在其中一个
				
int main() {
	Person p1(100, 90);	
	Person p2(100, 80);
	Person p3 = p1 + p2; 
	cout << p3.eng << endl << p3.math << endl;
	return 0;
}

1、重载运算符直接运算对象?

如果仔细查看上面代码,其实不难看出我们把对当前对象运算的细节都写在了运算符函数方法体中

	Person operator+(Person& p1) {  //成员函数
		Person temp;
		temp.eng = this->eng + p1.eng;
		temp.math = this->math + p1.math;
		return temp;
	}

2、重载运算符是如何工作的?

、上面代码中Person类,为它定义了一个operator +()的运算函数,以重载+运算符,以便能够将两个Person对象的分数相加,p1与p2都是都是类Person的对象,所以可以编写如下的等式

Person p3;
p3 = p1 + p2; 
p3 = p1.operator+(p2);编译器转换替换后

、编译器发现操作数即两个对象都是Person类对象因此使用相应的运算符函数替换上述运算符

、然后该函数将隐式的使用p1,因为p1作为对象调用函数,而显式的使用p2,因为p2被作为参数传递,来计算总和并返回这个值

、如果对两个对象直接进行运算并且重载了运算符,那么编译器会自动识别匹配相应的运算符函数替换运算,可以使用简单的+运算符表示法即 obj = obj1 + obj2,不用使用笨拙的函数表示法

3、可以将两个以上的对象进行运算吗?

例如:p1,p2,p3 都是Person的对象,可以这样做吗?

P5 = p1 + p2 + p3 ;

由于+是从左向右结合的运算符,因此上述语句首先被转化成下面 这样:
p5 = p1.operator(p2 + p3);

然后函数参数本身被转换成一个函数调用,结果如下:
p5 = p1.operator(p2.operator+(p3));

上述语句均是合法的

四、左移运算符重载

cout是一个ostream对象它是智能的能够识别所有C++基本类型。这是因为对于每种基本类型,ostream类声明中都包含了相应的重载的operator()定义。

也就是说,一个方法定义使用int,一个定义使用double参数,等等。因此要使cout能够识别Person对象,一种方法是将一个新的函数运算符定义添加到ostream类声明中,但修改ostream是个危险的主意,这样做会在标准接口上浪费时间。

相反,通过Person类声明来让Person类知道怎么使用cout。

class Person{
public:
//利用成员函数重载 左移运算符 p.operator<<(p)
void operator<<(Person &p){
							//不能这样写利用成员函数重载<<运算符
	}
}

全局函数重载左移运算符

#include<iostream>
using namespace std;


class Person {


	//添加全局重载<<运算符函数为友元函数就可以访问Person类中的私有成员属性
	friend ostream& operator <<(ostream& out, Person& p);
public:
	Person() {};
	Person(int a, int b) {
		this->math = a;
		this->eng = b;
	}

	//成员函数实现重载+运算符
	Person operator+(Person& p1) {
		Person temp;
		temp.eng = this->eng + p1.eng;
		temp.math = this->math + p1.math;
		return temp;
	}
private:
	int math,eng;
};

//全局函数实现重载左移运算符
ostream& operator <<(ostream &out,Person &p) {
	cout << "p.eng=" << p.eng << "\tp.math=" << p.math << endl;
	return out;
}

int main() {

	//实例化一个对象
	Person p(100,90);
	
	//这样就可以直接输出p对象了
	cout << p;

	system("pause");
	return 0;
}

五、不能重载的运算符

  • sizeof():sizeof运算符
  • . :成员运算符
  • .*:成员指针运算符
  • :: :作用域运算符
  • ?: :条件运算符
  • typeid:一个RTTI运算符
  • const_cast:强制类型转换运算符
  • dynamic_cast:强制类型转换运算符
  • reinterpret_cast:强制类型转换运算符
  • static_cast:强制类型转换运算符

六、可以重载的运算符

+-*/%^
&|~=!=<
>+=-=*=/=%=
^=&=|=<<>>>>=
<<===!=<=>=&&
||++- -,->*->
()[ ]newdeletenew [ ]delete[ ]

七、只能通过成员函数重载的运算符

  • = :赋值运算符
  • ( ):函数调用运算符
  • [ ]:下标运算符
  • ->:通过指针访问类成员的运算符

八、注意事项

对于很多运算符来说,可以选择使用成员函数或非成员函数来实现运算符重载。一般来说非成员函数应该是友元函数,这样它才能直接访问类的私有数据。

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++ 中的面向对象编程允许我们使用类和对象来组织和管理代码。在类中,可以定义成员函数和成员变量。成员函数是与类相关联的函数,它们可以访问类的成员变量并执行与该类相关的操作。成员变量是存储在类中的变量,它们描述了类的状态。 运算符重载C++ 中面向对象编程的一种强大功能。它允许您重新定义运算符以执行特定操作。例如,您可以重载“+”运算符以执行类对象的加法操作。运算符重载使您能够编写更直观和易于使用的代码。 友元函数是类的非成员函数,但它们可以访问类的私有成员。当您需要访问类的私有成员但不想使这些成员成为公共接口的一部分时,友元函数就会很有用。要声明一个友元函数,请在类定义中将其声明为友元。友元函数可以是全局函数或其他类的成员函数。 下面是一个示例类,其中包含运算符重载和友元函数: ```cpp #include <iostream> class MyClass { public: MyClass(int value) : value_(value) {} // 重载加号运算符,将两个 MyClass 对象相加 MyClass operator+(const MyClass& other) { return MyClass(value_ + other.value_); } // 将友元函数声明为 MyClass 的友元 friend void PrintValue(const MyClass& obj); private: int value_; }; // MyClass 的友元函数 void PrintValue(const MyClass& obj) { std::cout << "The value of MyClass is: " << obj.value_ << std::endl; } int main() { MyClass obj1(10); MyClass obj2(20); MyClass result = obj1 + obj2; PrintValue(result); return 0; } ``` 在这个例子中,我们定义了一个 MyClass 类,它包含一个成员变量 value_ 和一个构造函数。我们还重载了加号运算符,以便我们可以将 MyClass 对象相加。最后,我们定义了一个名为 PrintValue 的友元函数,该函数可以访问 MyClass 类的私有成员 value_。 在 main 函数中,我们创建了两个 MyClass 对象,将它们相加并将结果打印到控制台上。请注意,我们使用了友元函数 PrintValue 来打印 MyClass 对象的值,而不是直接访问 MyClass 对象的私有成员。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值