让Point
成为一个类,其实例可以显式地转换为wxPoint
:
class Point{
private:
int x;
int y;
public:
explicit operator wxPoint() const
{
return wxPoint(x, y);
}
// More stuff
}
我有一个函数返回对Point
类型对象的引用。这样一个函数的标题是:
const Point& GetPoint();
我的问题:定义以下Foo
函数是否安全?
const wxPoint& Foo() const{
return (wxPoint&) GetPoint();
}
首先,我使用Foo
实现了return (wxPoint) GetPoint();
,但是创建了一个新的(本地)对象,因此触发了有用的警告。此处显示的代码在没有警告的情况下编译。
我在这种类型的转换中找到的所有信息都是指继承的类,但这不是这种情况。
对于以这种方式投射参考时究竟发生了什么的解释将非常感激。
答案 0 :(得分:16)
实际上您的转换运算符从未被调用过。您将从point
返回对GetPoint
实例的引用。之后您使用了C样式转换,在您的情况下将等同于reinterpret_cast<>
(请参阅here)。您正在将对Point
的引用转换为对wxPoint
的引用,这两者是完全不相关的类型。另一方面,对返回引用的任何操作都是未定义的行为。
我的建议是始终使用C ++强制转换运算符。他们有好处:
答案 1 :(得分:13)
其他答案已经解释了将Point&
转换为wxPoint&
只是对编译器起作用,告诉它引用绑定的对象是wxPoint
对象,而不是真正。如果您尝试通过该引用访问wxPoint
对象,则您的程序将具有未定义的行为,因为它未绑定到wxPoint
对象。有时候当你骗到编译器时,它不会给你警告,只是要相信你没有做一些疯狂的事情。
修复是停止尝试返回对不存在的对象的引用:
wxPoint Foo() const {
return GetPoint();
}
这将使用您的转化运算符构造wxPoint
并按值返回,这是正常的。当没有任何内容可以绑定引用时,尝试通过引用返回是不行的。
答案 2 :(得分:4)
将引用转换为不相关的引用类型并不安全。虽然转换本身没有副作用,但通过另一种类型的引用访问原始对象具有未定义的行为(除非类型别名规则提供异常,就像它们在char
的情况下那样但在此不适用因为标准没有为wxPoint
)指定此类例外。
转换运算符不参与,没有任何区别。
对于以这种方式投射参考时究竟发生了什么的解释将非常感激。
&#34; C风格&#34; cast按优先顺序执行const_cast,static_cast或reinterpret_cast或其组合之一。没有static_cast适用于不相关的引用。
只有适用于将const Point&
转换为wxPoint&
的内容才是reinterpret_cast,后跟const_cast。 reinterpret_cast确实:
6)T1类型的左值表达式可以转换为对另一个类型T2的引用。结果是lvalue或xvalue引用与原始左值相同的对象,但具有不同的类型。没有创建临时,没有复制,也没有调用构造函数或转换函数。如果类型别名规则(见下文)
允许,则只能安全访问生成的引用
此处显示的代码在没有警告的情况下编译。
使用reinterpret_cast就像告诉编译器你知道你在做什么可能看起来像疯子一样,但不要担心,你知道你在做什么,所以不需要警告它。使用它应该非常小心。
由于C样式转换可能会隐式地重新解释,因此也需要非常小心。