C++运算符重载函数作为友元函数

Posted Linux编程学堂

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++运算符重载函数作为友元函数相关的知识,希望对你有一定的参考价值。

运算符重载函数作为友元函数

在前面的程序例子中对运算符“+”进行了重载,使之能用于两个字符串的相加。在该例中运算符重载函数 operator +(); 作为 my_string类中的成员函数。

可能有的读者会提出这样的问题:“+”是双目运算符,为什么在程序中重载的函数中只有一个参数呢?实际上,运算符重载函数有两个参数,由于重载函数是my_string类中的成员函数,所以,有一个参数是隐含的,运算符函数是用this指针隐式地访问类对象的成员,可以看到,重载函数operator + (); 访问了两个对象中的成员,一个是this指针指向的对象中的成员,一个是形参对象中的成员。

把 operator + (); 定义为 my_string类的一个成员函数之后,就是将运算符+重载为“类的成员函数”,C++编译系统将程序表达式:

str1 + str2;

解释为:

str1.operator + (str2);

那么,编译器在编译到“str1 + str2;”语句的时候,发现str1是my_string类,然后,后面接着一个“+”运算符,所以,就去my_string类寻找,发现重载了 operator +(); 函数,而且,这个函数是作为my_string类的成员函数(注意:后面还介绍了,重载的运算符作为友元函数的时候,不是属于当前类的成员函数,需要两个参数),所以,就调用:

my_string& my_string::operator + (my_string &str)

strcat(buf, str.buf);

return *this;

那么,对于“str1 + str2;”操作,就是str1对象调用自己重载的operator + ( ); 成员函数来执行,其中,str2 作为参数,得到如下的调用结果:

str1.operator + (str2); 

那么,str1 对象就是重载的 operator + (); 函数中的 this 指针指向的当前对象。

运算符重载函数除了可以作为类的成员函数以外,还可以是非成员函数。可以将前面的例子修改。将运算符“+”重载为适用于字符串加法 ,重载函数不作为成员函数,而放在类外,作为my_string类的友元函数。程序测试例子如下:

程序运行结果如下:

g++ test.cpp -o exe

wkf@ubuntu:~/c++$ ./exe

str = www.mylinux.vip13926572996

wkf@ubuntu:~/c++$

将定义的重载运算符声明为友元函数,而不是类的成员函数,那么,友元函数可以访问类的private类型成员。

所以,在my_string类中声明重载运算符函数声明为友元函数。同时将运算符函数改为有两个参数,也可以实现重载运算符函数的定义。在将运算符“+”重载为非my_string成员函数后,C++编译系统将程序中的表示 str1 + str2; 解释为:

operator + (str1, str2);

即执行 str1 + str2 相当于调用以下函数:

my_string& operator + (my_string &str1, my_string &str2)

my_string s;

strcpy(s.buf, str1.buf);

strcat(s.buf, str2.buf);

return s;

求出两字符串相加的操作。

有读者会提出这样的问题:为什么把运算符函数作为友元函数呢?理由很简单,因为运算符函数要访问my_string类对象中的成员,如果运算符函数不是my_string类的友元函数,而不是一个普通的函数,它是没有权利访问my_string类的私有成员的。

什么时候应该用成员函数方式,什么时候应该用友元函数方式呢?二者有何区别呢?如果将运算符重载函数作为成员函数,它可以通过 this 指针自由地访问本类的成员变量,因此,可以少写一个函数的参数,但是,必须要求运算表达式的第一个参数(即运算符左侧的操作数)是一个类对象,而且,与运算符函数的类型相同。因为,必须通过类的对象去调用该类的成员函数,而且,只有运算符重载函数返回值与该对象同类型结构才有意义。

把 operator + (); 定义为 my_string类的一个成员函数之后,就是将运算符+重载为“类的成员函数”,C++编译系统将程序表达式:

str1 + str2;

解释为:

str1.operator + (str2);

那么,编译器在编译到“str1 + str2;”语句的时候,发现str1是my_string类,然后,后面接着一个“+”运算符,所以,就去my_string类寻找,发现重载了 operator +(); 函数,而且,这个函数是作为my_string类的成员函数,就调用重载的operator+()成员函数。

函数需要访问类的私有成员,则必须把该函数声明为类的友元函数,例如,可以在my_string类中声明重载运算符的函数为该类的友元函数:

//重载运算符函数声明为友元

friend my_string& operator + (my_string &str1, my_string &str2);

在类外定义友元函数:

/*

定义的operator + (); 重载运算符函数,是一个普通的函数;

但是,为了能够操作my_string 类中的私有数据陈一个,就在my_string类中把它声明有友元函数。

*/

my_string& operator + (my_string &str1, my_string &str2)

my_string s;

strcpy(s.buf, str1.buf);

strcat(s.buf, str2.buf);

return s;

将双目运算符重载为友元函数时,在函数的形参列表中必须有两个参数,不能省略。形参的顺序任意,不要求第一个参数必须为类对象。

由于友元的使用破坏类的封装,因此,从原则上来说,要尽量地将运算符函数作为成员函数。但是,考虑到各个方面的因素,一般将单目运算符重载为成员函数,将双目运算符重载为友元函数。

说明:有的C++编译系统,如Visual C++6.0没有完全实现C++标准,它所提供不带后缀.h的头文件不支持把成员函数重载为友元函数。上面程序在GCC中能正常运行,而在Visual C++6.0 中会编译错误。但是,Visual C++所提供的老形式的带后缀.h的头文件可以支持此项功能,因此,可以将程序头两行修改如下,即可顺利运行:

#include <iostream.h>

以后遇到此类情况,亦可照此办理。


韦凯峰 Linux C/C++ 程序设计教程,Linux 系统编程,Openwrt 系统开发

以上是关于C++运算符重载函数作为友元函数的主要内容,如果未能解决你的问题,请参考以下文章

运算符重载

C++运算符重载中 重载为类的成员函数和重载为类的友元函数 的区别是啥?

为什么operator<<;;运算符重载一定要为友元函数呢?

运算符重载的函数作为类的成员函数和友元函数

cpp►运算符重载与友元friend

❥关于C++之成员与友元函数重载运算符