友元、运算符的重载

本文详细介绍了C++中的友元函数和友元类的概念及其使用,包括如何声明和定义友元函数,以及友元类中所有成员函数成为友元的情况。同时,文章探讨了运算符重载的原理,强调了双目运算符通常作为全局友元函数重载,单目运算符作为类成员函数重载,特别提到了赋值运算符的特殊情况。此外,还给出了多个示例来说明如何实现友元和运算符重载的实际应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、友元函数和友元类

1、友元函数

	在C++中我们我们通常可以将全局函数或者类的成员函数声明为类的友元函数,这样友元函数便可以访问类对象
中的私有成员。我们可以用friend关键字将其声明为友元函数。

1、将全局函数声明为类的友元函数
	以friend关键字声明的全局函数称为类的友元函数,友元函数可以通过类对象访问它的私有成员。可以在类内
对全局的友元函数进行声明,在类外对其进行定义。(也可以在类内对全局的友元函数进行定义,此时它仍然为全局
函数)。

2、将一个类的成员函数声明为另一个类的友元函数 
	它类似于将全局函数声明为类的友元函数,区别在于它是类的成员函数而已。

3、友元函数的主要作用:
	实际上在C++中将另一个函数声明为类的友元函数主要作用是服务于运算符的重载,友元的全局函数没有this
指针,因此只能通过类对象来访问类的私有成员。即全局的运算符重载函数的操作对象是类对象。

2、友元类

	将一个类B声明为另一个类A的友元类,则友元类B中所有的成员函数都是类A的友元函数。注意此时友元类需要
进行提前声明,友元的关系是单向的,不可传递的。

例:友元函数及友元类的使用范例

在这里插入图片描述
在这里插入图片描述

二、运算符的重载

	运算符的重载实际上是重载运算符函数,重载运算符函数有两种形式:全局的友元函数和类的成员函数。一般
将双目运算符重载为类的友元函数;将单目运算符重载为类的成员函数,此时注意类的成员函数有一个隐藏的形参
this指针。但是,对于赋值复合运算符=,+=, *=等必须重载为类的成员函数。
	运算符重载有一定的规则,例如不可以改变运算符的优先级、不可以改变运算符的操作数等等,同时还有一些
运算符是不能重载的,这里就不做太多阐述。

1、运算符重载函数的一般形式

1、运算符重载函数的函数名为 “operator 运算符” 
2、运算符的操作数作为运算符重载函数的参数
3、运算符的运算结果对应着运算符重载函数的返回值。

**注意:**
	标准输入流istream和标准输出流ostream的前面是不能用const关键字进行修饰的,因为标准输入或输出流
对象在进行IO操作时,实际上是不断的向标准输入流对象或标准输出流对象中写入数据的,他们的状态不断的在变
化,因此不能用const关键字进行修饰。

2、双目运算符的重载

一般将双目运算符重载为全局的友元函数,执行运算符相当于调用相应的运算符函数。
操作数1  运算符  操作数2 《====》 operator运算符(操作数1, 操作数2)

标准输入设备:istream类对象
cin >> obj;  《=====》 operator>>(cin, obj);
标准输出设备:ostream类对象  
cout << obj; 《====》 operator<<(cout, obj);

例:定义一个分数类,并从标准输入中完成对象的输入,利用标准输出来输出分数对象。

在这里插入图片描述
在这里插入图片描述

**3、重载单目运算符 **

	一般将单目运算符重载为类的私有成员函数,此时有一个隐藏的形参this指针。使用运算符实际上是调用运算
符重载函数。

	运算符 操作对象 《====》 操作对象.operator运算符();

例2:以分数类FS为基础,重载前置++运算符
分析:前置“++”运算符的结果为操作对象的值 
	  int a = 3;
	  cout << ++a << a << endl;
	  结果:4 4

前置“++”运算符重载函数:
FS operator++()
{
	this->son = this->son + this->mother;
	return *this;
}
例3:以FS类为基础,重载后置“++”运算符 
分析:int a = 3;
	  cout << a++ << a << end;
	  结果:3 4 

后置“++”运算符重载函数:
FS operator++(int)  //哑元,起到标识作用  
{
	FS temp = *this;
	this->son = this->son + this->mother;
	return temp
}

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

例4:赋值运算符的重载
	赋值复合运算符是特例,虽然它们是双目运算符,但是依然把他们重载为类的成员函数。
分析:
1、返回值类型为FS是为了达到链式赋值的效果:a = b = c
2、返回值使用引用的原因:避免调用拷贝构造函数,节省空间;达到可以使用“()”实现优先赋值的效果
int f1 = 1, f2 = 2, f3;
(f3 = f2) = f1;===>在返回值处使用引用时:f3 = 1, f2 = 2, f1 = 1;(说明:(f3=f2)的结果为f3)
			  ====>在返回值处不用引用时:f3 = 1, f2 = 1, f1 = 1;
FS &operator=(const FS &fs)
{
	//防止自赋值 
	if(&fs == this)
		return *this;
	this->son = fs.son;
	this->mother = fs.mother;
	return *this;
}

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值