&在c++的友元函数重载运算符符函数里是什么意思?

这是C++面向对象程序设计第七版的一个案例分析,里面包含了很多内容,有些我还没有掌握,比如输入输出流运算符的重载等等,但是我感觉这个案例很好,对于不会程序分块的读者该案例也有许多借鉴的地方。

这个类的值表示一天当中的时间。值采取24小时制进行输入输出

//将时间初始化为0:00(代表午夜) //前条件:对象已经有一个时间值 //前条件:对象已有一个时间值 //前条件:如果ins是一个文件输入流,那么ins已经与一个文件连接 //前条件:如果outs是一个文件输出流,那么outs已经与一个文件连接 //一下函数声明在重载的输入操作符>>的定义中使用: //前条件;流ins中的下一个输入是一个采用24小时制的时间,比如9:45或者14:45 //后条件:the_hour被设为时间的小时部分.冒号被舍弃,读取的下一个输入将是分钟数 //read_hour函数读取了小时数之后,这个函数从流ins中读取分钟数

有问题或者想一起学习的评论区留言。

为什么要对运算符进行重载:

C++预定义中的运算符的操作对象只局限于基本的内置数据类型,但是对于我们自定义的类型(类)是没有办法操作的。但是大多时候我们需要对我们定义的类型进行类似的运算,这个时候就需要我们对这么运算符进行重新定义,赋予其新的功能,以满足自身的需求。

C++运算符重载的实质:

运算符重载的实质就是函数重载或函数多态。运算符重载是一种形式的C++多态。目的在于让人能够用同名的函数来完成不同的基本操作。要重载运算符,需要使用被称为运算符函数的特殊函数形式,运算符函数形式:operatorp(argument-list)//operator 后面的'p'为要重载的运算符符号。

一个简单运算符重载实例:

(我在这篇博文里说过了,很简单,刚接触的朋友可以看一下,有代码)

(1)为了防止用户对标准类型进行运算符重载,C++规定重载后的运算符的操作对象必须至少有一个是用户定义的类型

但是如果你重载以后让着两个数相加为他们的乘积,这肯定是不合乎逻辑的。

可能重载以后会有二义性,导致程序不知道该执行哪一个(是自带的的还是重载后的函数)

(2)使用运算符不能违法运算符原来的句法规则。如不能将% 重载为一个操作数,

%index;这种是不被允许的。

(3)不能修改运算符原先的优先级。

(4)不能创建一个新的运算符,例如不能定义operator** (···)来表示求幂

(6)大多数运算符可以通过成员函数和非成员函数进行重载但是下面这四种运算符只能通过成函数进行重载:

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

(7)除了上述的规则,其实我们还应该注意在重载运算符的时候遵守一些明智的规则:例如:不要将+运算符重载为交换两个对象的值。

重载运算符的两种形式:
重载运算符有两种方式,即:

重载为类的成员函数||重载为类的非成员函数。

重载为类的非成员函数的时候:

通常我们都将其声明为友元函数,因为大多数时候重载运算符要访问类的私有数据,(当然也可以设置为非友元非类的成员函数。但是非友元又不是类的成员函数是没有办法直接访问类的私有数据的),如果不声明为类的友元函数,而是通过在此函数中调用类的公有函数来访问私有数据会降低性能。所以一般都会设置为类的友元函数,这样我们就可以在此非成员函数中访问类中的数据了。

下面我同意讲解一个经典的例子来说明一下这两者的区别、特点、要重载时可能出现的问题

现在我们有一个时间类,我们要进行的任务是对时间类的加减乘。或许你会觉得很简单,简单就对了,因为这更容易让你深入的理解到这二者


在主函数中,我们创建了weeding 和waxing连个对象,进行了操作。那么现在问题来了。

答案当然是不可以,我们还原下此语句:adjusted = total.operator*(1.5),换成1.5在乘号前面当然是不可以的。因为1.5不是对象。

这个时候有两种解决方式:

一:告诉每个人只能按照adjusted = total *1.5;  这种方式来,这种方式看起来当然是欠缺的。那么重头戏来了:

这样等价于:A = operator *(1.5,B)等价于:A = 1.5 * B;出于性能考虑,我们将其声明为friend 即友元函数(前面已经解释过为什么要声明为友元了):

接下来我们为了更好的了解重载运算符,来进行<<运算符的重载:

现在我们想让 cout<<adjusted; 这句话能直接执行输出,(显然这种输出方式如果不重载<<运算符是没有办法执行的。因为cout根本不知道输出adjusted的什么东西),对于<<的重载我们有两种版本:

第一种声明为成员函数

但是这样会存在一个问题:

(程序可以运行,更改也很少,可以试一试的呦);

那么最重要的问题来了,我们什么时候声明为成员函数,什么时候声明为非成员函数呢?

首先,我们要明白这句话:对于成员函数来说,一个操作数通过this指针隐式的传递,(即本身),另一个操作数作为函数的参数显示的传递;对于友元函数(非成员函数)两个操作数都是通过参数来传递的。

(1)一般来说,弹幕运算符重载为类的成员函数,双目运算符重载为类的友元函数(咳咳,一般情况下)

(2)双目运算符不能将 = 。 ()【】。-> 重载为类的友元函数。

(3)如果运算符的第一次操作数要求为隐式转换则必须为友元函数。

(4)当最左边的要求为类对象,而右边的是一个内置类型,则要为友元函数。

但是这两种方式不能同时声明定义,因为这会出现二义性。造成程序不知道该执行那个函数。在进行运算符重载的时候千万要注意造成二义性的情况。

ok。基本完了。如果你真正搞懂了这篇博文,最基本性的东西就可以了。

我要回帖

更多关于 友元函数重载运算符 的文章

 

随机推荐