C ++:转换运算符重载和引用

时间:2014-08-14 08:38:21

标签: c++ casting reference operator-overloading

C ++允许通过创建operator T()来重载类型转换,其中T是我们想要转换的类型。

现在,此功能如何与参考一起播放?例如:

struct Y{ int i; };

struct X{
    Y y;

    operator Y() const { return y; }
};

在这里,我们可以将X转换为Y,它只会返回包含的Y。但是如果我们想要对Y引用进行强制转换呢?例如,C ++允许我们这样做:

struct X{
    Y y;

    operator Y&(){ return y; }
    operator const Y&() const { return y; }
};

现在,我们可以将X转换为Y引用或const引用(也适用于const X)。

第一个和第二个例子的语义有什么不同吗?如果我想允许转换为引用,最好的方法是什么?

我可以想象即使我在没有任何operator T()的情况下编写&,C ++也可能允许转换通过引用返回结果(即,它可能以某种方式添加隐式operator T&()方法我指定operator T())。

例如,我希望以下代码可以工作:

int main(){
    X x;
    Y& y = x; // y now references the y inside x
    y.i = 5;
    std::cout << x.y.i << std::endl; // Should print 5 now
}

实现这一目标的最简单方法是什么?

3 个答案:

答案 0 :(得分:5)

  

声明operator T()是否暗示演员总是按值返回T

转换运算符的返回类型隐式正是它们转换为的内容。

  

[...]转换函数的类型是“函数不带参数返回conversion-type-id”。

     

§12.3.2[class.conv.fct]

答案 1 :(得分:3)

使用clang ++:

#include <iostream>

class   test
{
public:
  test(int n) : nb{n} {}

public:
  operator int() { return nb; }

  private:
    int nb;
};

int     main(void)
{
  test  t{42};

  int x = t;

  int& ref = t;   // error: non-const lvalue reference to type 'int' cannot bind to a value of unrelated type 'test'
  int&& rref = t; // compiles fine

  std::cout << x << std::endl;
}

这表示您确实返回了一个临时的新值。

帮助您在两种情况之间做出选择的真正问题是:您是否希望让人们修改您的内部成员(返回引用)并且该成员的复制成本很高(使用const引用而不是值)吗

答案 2 :(得分:3)

声明operator T()是否暗示演员总是按值返回T

这意味着转换运算符将按T的指定返回。是一个引用,指针或值。例如,给定某种类型(根据OP)Y

operator Y();
operator Y&();
operator Y*();

所有(使用cv限定版本的变体)都是有效的用户定义转换。要使用Y作为参考,您需要将其作为参考返回。

所以,是的,转换为不是引用的T意味着返回类型是一个值。这与general casting semantics内联 - 返回一个值。

第一个和第二个例子的语义有什么不同吗?

是的,存在语义差异。它们与引用与值返回类型的其他方法具有相同的语义差异。它们的不同之处在于以下两种方法不同;

Y get_y_value();
Y& get_y_ref();

备注

在同一个班级混合operator Y();operator Y&();可能导致模糊的重载(至少clang抱怨这个,但gcc似乎很乐意混合这两个)。

由于您的情况详情尚不清楚,我不会就哪一个更好的问题发表意见。通常,在实现用户定义的转换时,始终要考虑通常如何执行转换以及可能更频繁地返回rvalues。随着C ++ 11的出现,他们也赞成explicit;出于同样的原因,构造函数是explicit(如果特别需要,则不是。)