C++运算符重载形式——成员函数or友元函数

运算符重载是C++多态的重要实现手段之一。通过运算符重载对运算符功能进行特殊定制,使其支持特定类型对象的运算,执行特定的功能,增强C++的扩展功能。

运算符重载的我们需要坚持四项基本原则: (1)不可臆造运算符; (2)运算符原有操作数的个数、优先级和结合性不能改变; (3)操作数中至少一个是自定义类型; (4)保持重载运算符的自然含义。

一般来说,C++运算符重载可采用成员函数和友元函数,二者都可以访问类的私有成员,那么该采用哪一种呢?首先看一下二者的区别。 (1)当重载为成员函数时,会隐含一个this指针;当重载为友元函数时,不存在隐含的this指针,需要在参数列表中显示地添加操作数。 (2)当重载为成员函数时,只允许右参数的隐式转换;当重载为友元函数时,能够接受左参数和右参数的隐式转换。

如下代码:

class CString{
public:
    CString(char* str);
private:
    char* m_pStr;
};

因为CString的构造函数参数为一个char*,所以如果采用友元形式的operator +(const CString&, const CString&),那么char+CString和CString+char都能正常工作;而如果采用成员函数形式CString::operator+(const CString& rhs),则只能接受CString+char,如果执行char+CString则会编译出错。我们往往习惯CString+char和char+CString都应该被接受。需要注意的是,隐式转换由于临时变量的增加往往效率不高。如果应用程序对效率要求较高,针对以上类,建议选择定义多个运算符的友元重载版本:

CString& operator +(const CString&, const CString&);
CString& operator +(const char*, const CString&);
CString& operator +(const CString&, const char*);

一般而言,对于双目运算符,最好将其重载为友元函数;而对于单目运算符,则最好重载为成员函数。

但是也存在例外情况。有些双目运算符是不能重载为友元函数的,比如赋值运算符=、函数调用运算符()、下标运算符[]、指针运算符->等,因为这些运算符在语义上与this都有太多的关联。比如=表示“将自身赋值为…”,[]表示“自己的第几个元素”,如果将其重载为友元函数,则会出现语义上的不一致。

还有一个需要特别说明的就是输出运算符<<。因为<<的第一个操作数一定是ostream类型,所以<<只能重载为友元函数,如下:

friend ostream& operator <<(ostream& os, const Complex& c);
ostream& operator <<(ostream& os, const Complex& c){
    os << c.m_Real << “+” << c.m_Imag << “i” << endl;
    return os;
}

参考文献

[1]李健.编写高质量代码:改善C++程序的150个建议.第一版.北京:机械工业出版社,2012.1:131-134

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏chenjx85的技术专栏

leetcode-179-Largest Number(理解规则,自定义cmp函数进行排序)

1、这道题给定一个vector,里面存放着int类型的非负整数,要求把这些非负整数拼起来,尽可能拼成一个最大的整数。

20630
来自专栏静晴轩

类数组借用数组方法

于JavaScript如何将对象转化为数组对象,其用法写法已经很常见且完善,比如JQuery中的makeArray函数对此的实现,也是跟大家想的差不多,只是考虑...

38690
来自专栏前端吧啦吧啦

涨薪必备Javascript,快点放进小口袋!

32170
来自专栏软件开发

JavaSE学习总结(八)—— 异常处理(Exception)

一、理解异常及异常处理的概念 异常就是在程序的运行过程中所发生的不正常的事件,它会中断正在运行的程序。 异常不是错误 程序中关键的位置有异常处理,提高程序的稳定...

23990
来自专栏漫漫深度学习路

python 小工具总结

总结一些python编程中可能会用到的一些小工具 namedtuple 给tuple 起个名字 def namedtuple(typename, fiel...

22460
来自专栏Java进阶之路

Java8 Optional 的正确使用方式

21300
来自专栏HansBug's Lab

1798: [Ahoi2009]Seq 维护序列seq

1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec  Memory Limit: 64 MB Submit: 2930...

31350
来自专栏静晴轩

JavaScript对象length

前几日有在Javascript数组操作一文中稍提及了数组的length属性;深入一点探究,就发现JS这length确有许多难为所知的特性。这就边学边探究下这朵奇...

38780
来自专栏前端儿

表达式求值(1)

Dr.Kong设计的机器人卡多掌握了加减法运算以后,最近又学会了一些简单的函数求值,比如,它知道函数min(20,23)的值是20 ,add(10,98) 的值...

21920
来自专栏Coding迪斯尼

使用普拉特分析法解析极为复杂的算术表达式

13730

扫码关注云+社区

领取腾讯云代金券