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
}
实现这一目标的最简单方法是什么?
答案 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
(如果特别需要,则不是。)