具体情况如下:
我在系统API结构CGPoint
和CGSize
中定义了,我希望能够编写my_point = my_size
。
我无法修改CGPoint
struct,只能编写外部运算符。我可以编写二元运算符(+
,-
,...),但operator=
必须在struct内部声明。还有其他解决方案吗?
答案 0 :(得分:26)
要使表达式a = b;
编译,您需要operator=
类型为a
,其中包含b
类型的元素或类型可以从b
隐式转换。
第一种情况被排除,因为operator=
必须是该类的成员,并且由于您无法修改GLPoint
,因此您无法添加GLPoint& GLPoint::operator=( GLSize )
。
第二种情况遇到了同样的问题。从GLSize
到GLPoint
的隐式转换可以在GLPoint
(已排除)中作为隐式构造函数实现,或在operator GLPoint()
中作为成员GLSize
实现,需要修改GLSize
。转换不能作为自由函数添加。
备选方案使用非运算符语法,如添加自由函数assign
(或copy
):GLPoint& assign( GLPoint&, GLSize const & )
。
接下来的问题是你为什么要这样做。如果GLPoint
和GLSize
的设计者不认为某个尺寸应该可以分配给一个点,那么为什么你觉得它们应该是可分配的呢?通常,将类型保持分离是个好主意,因为这样可以使编译器检测到您可能在代码中犯的错误。
如果您允许从GLSize
到GLPoint
进行隐式转换,则可能会错误地键入:distance( point1, size2 )
,其中您指的是distance( point1, point2 )
,并且因为存在转换,编译器很乐意转换和应用。然后你会看到奇怪的结果,你会花费很多不错的调试时间来试图确定逻辑错误的位置。
除非域名对每个运算符在该上下文中的含义有一个非常明确的定义,否则我会不惜一切代价避免运算符重载。 每个人阅读您的代码会立即明白GLPoint(1,2) + GLSize(5)
代表什么,毫无疑问或含糊不清?如果情况并非如此,如果人们会感到惊讶甚至怀疑,那么请避免运算符重载并使用命名函数:move_up( GLPoint&, GLSize )
(或任何点+大小对您来说意味着)
答案 1 :(得分:3)
将CGSize
分配给CGPoint
时会发生什么?将其分解为某些操作员并在那里进行操作 - 例如
CGPoint& operator|=(CGPoint& cPoint, CGSize const& cSize)
{
// now set attributes of cPoint that you can extract from cSize
return cPoint;
}
这有什么困难?以下是一个示例:http://www.ideone.com/FZN20
答案 2 :(得分:2)
如果您可以从CGPoint派生或包装CGPoint并在整个代码中使用新类,那么您可以提供您喜欢的任何运算符。新类可以有一个转换运算符CGPoint
,以促进与现有函数的交互。
答案 3 :(得分:0)
其他答案接缝错过了明显的解决方案:添加一个函数将CGPoint转换为CGSize。当然,这不是你想要的(size = point
),但由于你不能修改两个类中的任何一个,这是唯一的方法:
CGSize ToSize( const CGPoint &pt )
{
CGSize res = ...
// do the conversion
return res;
}