Можно ли написать оператор автоматического приведения вне структуры? - PullRequest
21 голосов
/ 25 мая 2011

Точная ситуация следующая: я определил в системных API структурах CGPoint и CGSize, и я хочу иметь возможность писать my_point = my_size.Я не могу изменить CGPoint структуру, только могу написать внешний оператор.Я могу написать бинарные операторы (+, -, ...), но operator= должно быть объявлено внутри struct.Так есть ли другое решение?

Ответы [ 4 ]

26 голосов
/ 25 мая 2011

Чтобы скомпилировать выражение 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 ) (или любой другой тип точки + размер)

3 голосов
/ 25 мая 2011

Когда вы назначаете 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 голосов
/ 25 мая 2011

Если вы можете наследовать или оборачивать CGPoint и использовать новый класс вместо этого в своем коде, то вы можете предоставить любые операторы, которые вам нравятся.Новый класс может иметь оператор преобразования в CGPoint, облегчающий взаимодействие с существующими функциями.

0 голосов
/ 25 мая 2011

Другие ответы кажутся пропущенными для очевидного решения: добавьте функцию для преобразования CGPoint в CGSize.Конечно, это не совсем то, что вы хотите (size = point), но поскольку вы не можете изменить ни один из двух классов, это единственный способ:

CGSize ToSize( const CGPoint &pt )
{
  CGSize res = ...
  // do the conversion
  return res;
}
...