是否可以在结构外编写自动转换操作符?

时间:2011-05-25 07:18:27

标签: c++ casting operator-keyword

具体情况如下: 我在系统API结构CGPointCGSize中定义了,我希望能够编写my_point = my_size。 我无法修改CGPoint struct,只能编写外部运算符。我可以编写二元运算符(+-,...),但operator=必须在struct内部声明。还有其他解决方案吗?

4 个答案:

答案 0 :(得分:26)

要使表达式a = b;编译,您需要operator=类型为a,其中包含b类型的元素或类型可以从b隐式转换。

第一种情况被排除,因为operator=必须是该类的成员,并且由于您无法修改GLPoint,因此您无法添加GLPoint& GLPoint::operator=( GLSize )

第二种情况遇到了同样的问题。从GLSizeGLPoint的隐式转换可以在GLPoint(已排除)中作为隐式构造函数实现,或在operator GLPoint()中作为成员GLSize实现,需要修改GLSize。转换不能作为自由函数添加。

备选方案使用非运算符语法,如添加自由函数assign(或copy):GLPoint& assign( GLPoint&, GLSize const & )

接下来的问题是你为什么要这样做。如果GLPointGLSize的设计者不认为某个尺寸应该可以分配给一个点,那么为什么你觉得它们应该是可分配的呢?通常,将类型保持分离是个好主意,因为这样可以使编译器检测到您可能在代码中犯的错误。

如果您允许从GLSizeGLPoint进行隐式转换,则可能会错误地键入: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;
}