Apr 29

C++ 中重载 + 操作符的正确方法 不指定

felix021 @ 2008-4-29 00:15 [IT » 程序设计] 评论(0) , 引用(0) , 阅读(3252) | Via 本站原创 | |
from http://www.vckbase.com/document/viewdoc/?id=1356

C++ 中重载 + 操作符的正确方法

作者:Danny Kalev
编译:MTT 工作室

原文出处:Overloading Operator + the Right Way

摘要:本文概要性地介绍如何选择正确的策略来为用户定义类型重载 + 操作符。

--------------------------------------------------------------------------------
  用户定义的类型,如:字符串,日期,复数,联合体以及文件常常重载二元 + 操作符以实现对象的连接,附加或合并机制。但是要正确实现 + 操作符会给设计,实现和性能带来一定的挑战。本文将概要性地介绍如何选择正确的策略来为用户定义类型重载这个操作符。
考虑如下的表达式: int x=4+2;
  内建的 + 操作符有两个类型相同的操作数,相加并返回右值 6,然后被赋值给 x。我们可以断定内建的 + 是一个二元的,对称的,可交换的操作符。它产生的结果的类型与其操作数类型相同。按照这个规测,当你为某个用户定义类型重载操作符时,也应该遵循相应内建操作符的特征。
  为用户定义类型重载 + 操作符是很常见的编程任务。尽管 C++ 提供了几种实现方法,但是它们容易使人产生设计上的误解,这种误解常常影响代码的正确性,性能以及与标准库组件之间的兼容性。

下面我们就来分析内建操作符的特征并尝试模仿其相应的重载机制。

第一步:在成员函数和非成员函数之间选择
你可以用类成员函数的方式实现二元操作符如:+、- 以及 ==,例如:

class String
{
public:
       bool operator==(const String & s); // 比较 *this 和 s
};
  这个方法是有问题的。相对于其内建的操作符来说,重载的操作符在这里不具有对称性;它的两个参数一个类型为:const String * const(这个参数是隐含的),另一个类型为:const String &。因此,一些 STL 算法和容器将无法正确处理这样的对象。
  另外一个可选方法是把重载操作符 + 定义为一个外部(extern)函数,该函数带两个类型相同的参数:

String operator + (const String & s1, const String s2);
这样一来,类 String 必须将该重载操作符声明为友元:

class String
{
public:
       friend String operator+(const String& s1,const String&s2);
};
第二步:返回值的两难选择
  如前所述,内建操作符 + 返回右值,其类型与操作数相同。但是在调用者堆栈里返回一个对象效率很低,处理大型对象时尤其如此。那么能不能返回一个指针或引用呢?答案是不行。因为返回指针破坏参数类型与返回值类型应该相同的规则。更糟的是,链接多个表达式将成为不可能:

String s1,s2,s3;
String res;
res=s1+s2+s3; // 不可能用 String* 作为返回值
  虽然有一个办法可以定义额外的 + 操作符重载版本,但这个办法是我们不希望用的,因为返回的指针必须指向动态分配的对象。这样的话,如果调用者释放(delete)返回的指针失败,那么将导致内存泄漏。显然,返回 String* 不是一个好主意。
  那么返回 String& 好不好呢?返回的引用必须一定要是一个有效的 String。它避免了使用动态对象分配,该方法返回的是一个本地静态对象的引用。静态对象确实解决了内存泄漏问题,但这个方法的可行性仍然值得怀疑。在一个多线程应用中,两个线程可能会并发调用 + 操作符,因此造成 String 对象的混乱。而且,因为静态对象总是保留其调用前的状态,所以有必要针对每次 + 操作符的调用都清除该静态 String 对象。由此看来,在堆栈上返回结果仍然是最安全和最简单的解决方案。

作者简介
  Danny Kalev 是一名通过认证的系统分析师和软件工程师,专攻 C++ 和形式语言理论。1997 年到 2000 年期间,他是 C++ 标准委员会成员。最近他以优异成绩完成了他在普通语言学研究方面的硕士论文。 业余时间他喜欢听古典音乐,阅读维多利亚时期的文学作品,研究 Hittite、Basque 和 Irish Gaelic 这样的自然语言。其它兴趣包括考古和地理。Danny 时常到一些 C++ 论坛并定期为不同的 C++ 网站和杂志撰写文章。他还在教育机构讲授程序设计语言和应用语言课程。




欢迎扫码关注:




转载请注明出自 ,如是转载文则注明原出处,谢谢:)
RSS订阅地址: https://www.felix021.com/blog/feed.php
Tags: ,
发表评论
表情
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
打开HTML
打开UBB
打开表情
隐藏
记住我
昵称   密码   *非必须
网址   电邮   [注册]