C++ C++;:强制转换运算符重载和引用
C++允许通过创建一个C++ C++;:强制转换运算符重载和引用,c++,casting,reference,operator-overloading,C++,Casting,Reference,Operator Overloading,C++允许通过创建一个操作符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&(){ retu
操作符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
)
第一个例子和第二个例子的语义有什么不同吗?如果我想允许对引用进行强制转换,最好的方法是什么?
我可以想象,即使我写了代码>操作符To(),没有任何代码>和代码>,C++也可以允许强制引用返回一个结果(也就是说,当我指定<代码>操作符T-())/>代码>时,它可能不知何故添加隐式<代码>操作符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
}
intmain(){
X;
Y&Y=x;//Y现在引用x中的Y
y、 i=5;
标准::cout
声明运算符T()
是否意味着强制转换总是按值返回T
对
转换运算符的返回类型隐式地正是它们转换为的类型
[…]转换函数的类型为“不带参数的函数返回转换类型id”
§12.3.2[类别转换功能]
用叮当声++:
#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;
}
#包括
课堂测试
{
公众:
测试(int n):nb{n}{}
公众:
运算符int(){return nb;}
私人:
int nb;
};
内部主(空)
{
测试t{42};
int x=t;
int&ref=t;//错误:对类型“int”的非常量左值引用无法绑定到不相关类型“test”的值
int&&rref=t;//编译很好
std::cout声明运算符T()
是否意味着强制转换总是按值返回T
这意味着转换运算符将返回T
指定的值。可以是引用、指针或值。例如,给定某种类型(根据OP)Y
:
operator Y();
operator Y&();
operator Y*();
所有(带有cv限定变体)的有效用户定义转换。若要使用Y
作为参考,您需要将其作为参考返回
因此,是的,转换为非引用的T
意味着返回类型是一个值。这与返回的-a值是内联的
第一个示例和第二个示例的语义有什么不同吗?
是的,存在语义差异。它们的语义差异与其他引用和值返回类型的方法相同。它们的不同之处与以下两种方法的不同之处相同
Y get_y_value();
Y& get_y_ref();
注释
在同一个类中混合使用运算符Y();
和运算符Y&();
可能会导致不明确的重载(至少clang对此表示不满,但gcc似乎乐于将两者混合使用)
我不想知道在这里,哪一种方法更好,因为你的情况的细节还不清楚。一般来说,当实现用户定义的转换时,总是考虑如何执行通常的转换,并且经常会返回rValue.随着C++ 11的出现,他们也倾向于使用<代码>显式< /代码>;出于同样的原因,构造函数是显式的
(如果特别需要,也可以不显式)。您是在询问返回值和引用之间的语义差异,还是返回常量引用和非常量引用之间的语义差异?@无用:我是在问:是否声明运算符T()
(不带&
)暗示强制转换总是按值返回T
?或者在某些情况下有一些规则可以作为参考返回T
?我试图澄清这个问题。谢谢!但是如果我声明下面的示例(使用T&
和const T&
),那么我是否可以省略T
cast,因为reference+const reference总是可以使用的?是的,因为:“返回“reference to cv2 X”的转换函数根据引用类型返回“cv2 X”类型的左值或X值,因此在选择候选函数的过程中被视为产生X。”§13.3.1.5[over.match.conv]@gexicide:如果通过参考版本提供,您几乎肯定希望省略T
版本,否则您将需要客户端代码手动消除大量客户端使用的歧义(即显式编写x.operator Y()
或x.operator Y&()
).如果是C++11,则返回Y
的对该重载的右值引用是明智的@tonyd@Yakk:有时-有时返回的Y
可能会立即用作表达式的一部分,并且不会绑定任何引用,或者可能会被引用以进行计算,但不会从中复制……是的,我想让人们修改memb呃。但是,我不知道它是否是一个昂贵的副本,因为它的类型是一个模板参数,所以它可以依赖。我只是想给客户端最高的灵活性。那么什么是最佳的强制转换操作符集?(“intx”应该是“intx”。。除此之外)没有人提到隐式cast运算符重载不是很好的样式?只提供模板setter和getter(一个重载用于值复制,一个重载用于l引用,一个重载用于r引用)怎么样@gexicide您的第二个选择,引用和const引用转换标记为const。@DarioOO好吧,这取决于您想要实现什么,cast运算符比简单的getter/setter具有更强的语义,它基本上意味着您的类型足够兼容,因此可以将一个转换为另一个。隐式转换在某些ca中很有意义虽然它可以成为