【C++入门】运算符重载详解

1、什么是运算符重载

不可重载运算符运算符含义
.成员访问运算符
“->*”和“.*”成员指针访问运算符
::域运算符
sizeof长度运算符
? :条件运算符
#预处理符号

(1)运算符:运算符分为算术运算符(+、-、*、/)、关系运算符(=、!=、==)、逻辑运算符(&&、!)等;
(2)运算符重载:给运算符赋予新的含义,可以根据运算符操作的对象进行恰当的操作;
(3)不是所有的运算符都支持运算符重载,有的运算符的含义在任何情况下都是确定的,所以不需要重载;

2、为什么需要运算符重载?

(1)运算符都是有默认的含义的,比如"+“符号,表示两个对象的相加,对于像int、long等C++原生的类型,”+“符号可以很好的处理,因为这是明确且不变的;但是”+“进行相加的对象时用户自定义的,那默认的”+“在处理时就会出现问题,因为编译器根本不知道用户会如何定义类,更不知道怎么对两个对象进行相加的操作,这时候就需要定义类的程序员去将”+“号进行重载,重新定义针对类的”+“运算符操作;
(2)程序中操作都是以函数为单位的,运算符能进行操作实质也是编译器帮我们把运算符和某个函数进行绑定,当我们使用”+"运算符时,编译器会自动帮我们调用默认的相加函数;
(3)编译器提供的运算符默认函数,只能进行能提前确定的一些操作,基本上就是对C++原生自带类的操作,当涉及用户自定义的类操作时,就会出现问题,这时候就需要定义类的程序员自己去重新定义类的运算符,也就是运算符重载;
(4)当程序执行时,会去匹配运算符绑定的函数,类似于函数重载,如果没有对运算符进行重载就调用默认的运算符函数,如果匹配上重载的运算符函数就调用重载的函数;

3、运算符重载的优劣

class sample
{
	int a;
	int b;
	int c;
};

sample d, e, f;

//使用运算符重载
f = d + e;

//不使用运算符重载
f.a = d.a + d.a;
f.b = d.b + d.b;
f.c = d.c + d.c;

(1)首先运算符重载不是必须的,不使用运算符重载一样可以完成功能,C语言就没有运算符重载不也一样工作;
(2)重载运算符可以使得代码更简洁;参考上面的代码,如果针对sample类重载"+“运算符就可以很简洁的执行两个sample类对象的加操作,如果不重载”+"运算符就必须显示的执行每个类成员的相加操作;
(3)运算符重载机制加大了类库作者的工作量,减少了调用类库写功能的人的书写量,因为运算符重载的代码是类库作者写的;

4、运算符重载示例

4.1、示例代码

#include <iostream>

using namespace std;

//表示坐标的类
class coordinate
{
public:
	int x;					// x轴坐标
	int y;					// y轴坐标

	//构造函数
	coordinate();
	coordinate(int x0, int y0);

	//打印坐标的值
	void print(void);
	
	// 重载"+"运算符
	coordinate operator+(const coordinate& other);
	
};

coordinate::coordinate()
{
	x = 0;
	y = 0;
};

coordinate::coordinate(int x0, int y0)
{
	x = x0;
	y = y0;
};

void coordinate::print(void)
{
	cout << "(" << this->x << ", " << this->y << ")" << endl;
}

coordinate coordinate::operator+(const coordinate& other)
{
	coordinate tmp;
	tmp.x = this->x + other.x;
	tmp.y = this->y + other.y;
	
	return tmp;
}

int main(void)
{
	coordinate a(1, 3);
	coordinate b(2, 6);
	coordinate c;
	
	//执行加操作,此时因为coordinate类重载加号运算符,会调用coordinator类重载的加函数
	c = a + b;			
	//c = a.operator+(b); //上面的c = a + b等同于:c = a.operator+(b);
	
	a.print();
	b.print();
	c.print();
	
	return 0;
}

(1)运算符重载就是在类中去重新实现运算符对应的函数;
(2)运算符重载的函数格式:返回值 operator要重载的运算符
(3)运算符重载基本都是双目运算符,符号左边的是this,右边的是other;意思是运算符调用的是左边对象的运算符重载函数,右边的对象作为传参;
(4)比如:c = a + b 等同于 a.operator+(b); c = b + a 等同于 b.operator+(a);

4.2、代码运行结果

[root#]$ ./app 
(1, 3)
(2, 6)
(3, 9)

5、"+"重载后a+b一定等于b+a?

coordinate coordinate::operator+(const coordinate& other)
{
	tmp.x = this->x + other.x * 2;
	tmp.y = this->y + other.y * 2;
	
	return tmp;
}

(1)a+b不一定等于b+a,这取决于我们运算符重载函数是如何定义的;
(2)在上面的代码中,将"+"运算符重载函数改成上面的形式,a+b就不等于b+a;
(3)a + b 等同于 a.operator+(b),其中this是a,other是b;b + a 等同于 b.operator+(a),其中this是b,other是a;

6、拷贝构造函数和"="赋值运算符重载的区别

6.1、示例代码

#include <iostream>

using namespace std;

class coordinate
{
public:
	int x;					// x轴坐标
	int y;					// y轴坐标
	
	coordinate();
	coordinate(int x0, int y0);
	
	// 拷贝构造函数
	coordinate(const coordinate& rhs);
	
	void print(void);
	
	// =的运算符重载函数
	coordinate& operator=(const coordinate& other);

};

coordinate::coordinate()
{
	x = 0;
	y = 0;
};

coordinate::coordinate(int x0, int y0)
{
	cout << "coordinate construtor" <<endl;
	x = x0;
	y = y0;
};

// 拷贝构造函数
coordinate::coordinate(const coordinate& src)
{
	cout << "---copy coordinate construtor---" << endl;
	this->x = src.x;
	this->y = src.y;
}

void coordinate::print(void)
{
	cout << "(" << this->x << ", " << this->y << ")" << endl;
}

coordinate& coordinate::operator=(const coordinate& other)
{
	cout << "operator=" << endl;

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

int main(void)
{
	//普通的构造函数
	coordinate a(1, 2);

	//拷贝构造函数
	coordinate b = a;

	// =运算符重载函数
	coordinate c;
	c = a;

	a.print();
	b.print();
	c.print();

	return 0;
}

6.2、代码执行结果

[root#]$ ./app 
coordinate construtor
---copy coordinate construtor---
operator=
(1, 2)
(1, 2)
(1, 2)

(1)在定义对象的同事用同类型的对象来初始化,调用的是拷贝构造函数;
(2)定义好对象后,再用同类型的对象来赋值,此时调用的是"="运算符重载函数;

7、赋值运算符重载返回引用和对象的区别

(1)编译器并没有规定运算符重载函数的返回值,可以返回对象、引用、指针或者void;
(2)如果重载函数返回值是void,则重载的函数不支持连续操作,比如:连加操作、连续赋值操作;
(3)如果重载函数返回值是对象,则在连续操作时是值传递,涉及对象不停的复制,比较消耗资源;
(4)如果重载函数返回值是对象,则在连续操作时不涉及对象的复制,节省资源;

8、友元函数实现运算符重载

8.1、示例代码

#include <iostream>

using namespace std;

class coordinate
{
public:
	int x;					// x轴坐标
	int y;					// y轴坐标
	
	coordinate(void){	x = 0;	y = 0;};
	coordinate(int x0, int y0);
	
	void print(void);

	//友元函数
	friend coordinate operator+(const coordinate& a, const coordinate& b);
	
};

coordinate::coordinate(int x0, int y0)
{
	x = x0;
	y = y0;
};

void coordinate::print(void)
{
	cout << "(" << this->x << ", " << this->y << ")" << endl;
}

// 用独立函数来实现+的运算符重载
coordinate operator+(const coordinate& a, const coordinate& b)
{
	coordinate tmp;
	
	tmp.x = a.x + b.x;
	tmp.y = a.y + b.y;
	
	return tmp;
}


int main(void)
{
	coordinate a(1, 3);
	coordinate b(2, 4);
	coordinate c;
	
	c = a + b;	// 相当于是 c = operator+(a, b);
	
	a.print();
	b.print();
	c.print();

	return 0;
}

(1)之前的代码实现运算符重载,重载函数都是属于某个类的,上面的示例代码是用友元函数来实现运算符重载;
(2)友元函数实现运算符重载,因为友元函数不属于类本身,也就不能使用this指针,所以需要将两个操作数都传递进去;

8.2、友元函数和成员函数实现运算符重载的选择?

(1)两种方式C++都是支持的,功能上都可以实现,运算符选择任意一种来实现运算符重载都是可以的;
(2)一般建议将双目运算符重载用友元函数实现,单目运算符重载用成员函数实现;
(3)双目运算符用成员函数实现重载:两种操作数的地位其实是不相等的,运算符左侧的操作是用this指针表示,右侧的操作数是传进去的参数,地位不相等,容易造成a+b不等于b+a;
(4)单目运算符用成员函数实现重载:因为单目运算符只涉及一个操作对象,直接使用成员函数的this指针就可以实现功能,很方便;

  • 2
    点赞
  • 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
发出的红包

打赏作者

正在起飞的蜗牛

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

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

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

打赏作者

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

抵扣说明:

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

余额充值