Точная ситуация следующая:
Я определил в системных API-структурах CGPoint
и CGSize
, и я хочу иметь возможность писать my_point = my_size
.
Я не могу изменить структуру CGPoint
, но может писать внешний оператор. Я могу написать двоичные операторы (+
, -
,...), но operator=
должен быть объявлен внутри структуры. Итак, есть ли другое решение?
Можно ли написать оператор автозапуска вне структуры?
Ответ 1
Чтобы скомпилировать выражение 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 )
(или любой другой размер + размер означает для вас)
Ответ 2
Когда вы назначаете 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
Ответ 3
Если вы можете получить или обернуть CGPoint и использовать новый класс вместо всего кода, то вы можете предоставить любые операторы, которые вам нравятся. Новый класс может иметь оператор преобразования CGPoint
, способствующий взаимодействию с существующими функциями.
Ответ 4
Другие ответы швы, чтобы пропустить очевидное решение: добавьте функцию для преобразования CGPoint в CGSize. Конечно, это не совсем то, что вы хотите (size = point
), но поскольку вы не можете изменить один из двух классов, это единственный способ:
CGSize ToSize( const CGPoint &pt )
{
CGSize res = ...
// do the conversion
return res;
}