快速业务通道

泛型编程-转移构造函数(Generic Programming: Move Constructor)

作者 佚名技术 来源 程序设计 浏览 发布时间 2012-06-29
别是常量值和无名的临时对象不能被这个重载版本接受,这是一个好的起点。现在我们只剩下在常量对象和非常量临时对象之间作出区分了。

为了达到这个目的,我们采取了一种技术,定义两个替身类型[译注:原文是type sugar,嘿嘿,如果你愿意,可以叫他类型砂糖,如果你喜欢吃糖的话。]ConstantString和TemporaryString,并且定义了从String对象到这些对象转型运算符:

class String;
//常量String的替身类型
struct ConstantString
{
  const String* obj_;
};
//临时String的替身类型
struct TemporaryString : public ConstantString {};
class String
{
public:
  //...构造函数,析构函数,运算符,等等......
  operator ConstantString() const
  {
    ConstantString result;
    result.obj_ = this;
    return result;
  }
  operator TemporaryString()
  {
    TemporaryString result;
    result.obj_ = this;
    return result;
  }
};

现在定义下面三个重载版本:

//绑定非常量临时对象
void Connect(TemporaryString);
//绑定所有的常量对象(左值和临时对象)
void Connect(ConstantString);
//绑定非常量左值
void Connect(String& str)
{
  //调用另一个重载版本
  Connect(ConstantString(str));
}

常量String对象被Connect(ConstantString)吸收。没有其他绑定可以工作,另两个仅仅被非常量String对象调用。

临时对象不能调用Connect(String&)。然而它们可以调用Connect(TemporaryString)或者Connect(ConstantString),前者必然被选中而不发生歧义。原因是因为TemporaryString从ConstantString派生而来,一个应该注意的诡计。

考虑一下ConstantString和TemporaryString都是独立的类型。那么,当要求复制一个临时对象时,编译器将同等的对待operator TemporaryY()/Y(TemporarY)或者operator ConstantY() const/Y(ConstantY)。

为什么是同等的?因为就选择成员函数来说,非常量到常量转型是“无摩擦的”。

因而,需要告诉编译器更多的选择第一个而不是第二个。那就是继承在这里的作用。现在编译器说:“好吧,我猜我要经过ConstantString或者TemporaryString...,但是等等,派生类TemporaryString是更好的匹配!”

这里的规则是从重载候选中选择函数时,匹配的派生类被视作比匹配的基类更好。

[译注]

我对上述代码稍作修改,从std::string派生了String,并在此基础上按照Mojo的方式修改,结果在gcc3.2编译器下的确如作者指出的行为一般无二。这条重载的决议规则很少在C++书籍中提到,Wang Tianxing从烟波浩淼的标准文本中找出了这条规则:

13.3.3.2 Ranking implicit conversion sequences [over.rank]
4 [...]
-- If class B is derived directly or indirectly
  from class A and class C is derived directly
  or indirectly from B,
 [...]
-- binding of an expression of type C to a
   object of type B is better than binding
   an expression of type C to a object
   of object A,

上面这些标准中的条款,是从隐式转型的转换等级中节选出来的,大致的意思是说,如果C继承B,而B继承A,那么类型为C的表达式绑定到B的对象比到A的对象更好,这是上面叙述的技术的标准依据。此外,类似的引用和指针的绑定也适用于此规则,这里省略了这些条款。

最后一个有趣的花样是,继承不需要必须是public的。存取规则和重载规则是不冲突的。

让我们看看Connect如何工作的例子:

String s1("http://moderncppdesign.com");
// 调用Connect(String&)
Connect(s1);
// 调用operator TemporaryString()
// 接下

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号