Почему в этом случае перегруженный оператор друга предпочтительнее оператора преобразования
-
19-09-2019 - |
Вопрос
Привет, у меня есть такой код, я думаю, что и перегруженный оператор друга, и оператор преобразования имеют аналогичную функцию.Однако почему в этом случае вызывается перегруженный оператор друга?Каковы правила?
Спасибо!
class A{
double i;
public:
A(int i):i(i) {}
operator double () const { cout<<"conversion operator"<<endl;return i;} // a conversion operator
friend bool operator>(int i, A a); // a friend funcion of operator >
};
bool operator>(int i, A a ){
cout<<"Friend"<<endl;
return i>a.i;
}
int main()
{
A aa(1);
if (0 > aa){
return 1;
}
}
Решение
Никакого преобразования не требуется для перегруженного operator>
быть вызванным.Для того, чтобы встроенный operator>
для вызова необходимо одно преобразование (пользовательский оператор преобразования.Разрешение перегрузки предпочитает варианты с меньшим количеством необходимых преобразований, поэтому перегруженный operator>
используется.
Обратите внимание: если бы вы изменили определение вашего перегруженного operator>
быть, например:
friend bool operator>(double i, A a);
вы получите ошибку компиляции, потому что оба перегруженных operator>
и встроенный operator>
потребуется одно преобразование, и компилятор не сможет разрешить неоднозначность.
Другие советы
Я не утверждаю, что мой ответ соответствует стандартам, но давайте подумаем логически.
Когда вы нажмете на эту строку:
0 > aa
У вас есть два варианта.Либо вы звоните указанному оператору:
friend bool operator>(int i, A a);
Это совместимо на 100 %, или вы можете выполнить два преобразования, чтобы добраться до пункта назначения!Какой из них вы бы выбрали?
Если вы добавите оператор преобразования, объект типа A может быть преобразован в двойной, когда вы меньше всего этого ожидаете.
Хорошая программа не допускает случайного использования своих классов, а оператор преобразования открывает возможность использования класса в целом ряде непредвиденных ситуаций (обычно ситуации, когда вы ожидаете ошибку времени компиляции, не происходят, потому что автоматического преобразования типа).
В результате к операторам преобразования (и конструкторам с одним аргументом) следует относиться с некоторой осторожностью из-за ситуаций, когда компилятор может выполнить преобразование, когда вы меньше всего этого ожидаете.
Его называют потому, что это полное совпадение в контексте выражения 0 > aa
.На самом деле, трудно понять, как вы пришли к вопросу «почему».По логике, можно было бы ожидать вопроса «почему», если друг не были звонил в этом случае.
Если вы измените выражение на 0.0 > aa
, вызов станет неоднозначным, поскольку ни один путь будет лучше другого.