Перегрузка разных типов в C++

Предположим, у нас есть следующий класс:

class Rational { // Represents rational number. n=1/2=d for example.
public:
  int n = 0;
  int d = 1;
};

Rational x = Rational();
x.n = 1;
x.d = 2;

Можно ли сделать такую ​​перегрузку, чтобы 3 * x вместо ошибки выдавал 3/2?

Мой учитель сказал, что перегрузка происходит только между объектами одного типа, но почему мы можем делать перегрузку между cout, который имеет тип ostream, и объектом типа Rational, а не типа int и Rational?

Вам нужно реализовать арифметические операторы для вашего класса. См. здесь (ищите раздел(ы) "арифметика"): stackoverflow.com/questions/4421706/….

wohlstad 17.05.2022 18:17

Если реализовать функции operator, то можно сделать 3 * x и получится 3 * n / d

2pichar 17.05.2022 18:17

Re: перегрузка происходит только между объектами одного типа. Перегрузка происходит только в функциях, и это по определению означает использование разных чисел, типов или аргументов. Вы, конечно, можете перегрузить оператор *, где он принимает ваш класс и целочисленное значение.

The Dreams Wind 17.05.2022 18:18
«Мой учитель сказал, что перегрузка происходит только между объектами одного типа». Ваш учитель не прав.
Jarod42 17.05.2022 18:19

«Мой учитель сказал, что перегрузка происходит только между объектами одного и того же типа». Либо это не то, что они сказали, либо они не правы, и Rational& operator*(Rational& lhs, float rhs) {lhs.n *= rhs; return lhs; }, кажется, делает то, что просят.

Borgleader 17.05.2022 18:19

Это выглядит довольно странно operator*, если он изменяет один из своих аргументов. Я ожидаю, что operator* вернет Rational, а operator*= изменит левую часть и вернет Rational&.

Nathan Pierson 17.05.2022 18:22

Конечно. * обычно должен брать const Rational &. Хотя я вижу преимущество наличия Rational operator *(Rational &&lhs, float rhs), например. большая матрица.

Goswin von Brederlow 17.05.2022 19:17
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
Четыре эффективных способа центрирования блочных элементов в CSS
Четыре эффективных способа центрирования блочных элементов в CSS
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то...
1
7
57
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете написать, например

Rational operator *( const Rational &r, int x )
{
    return { r.n * x, r.d };
}

Rational operator *( int x, const Rational &r )
{
    return { r.n * x, r.d };
}

Вы можете перегружать операторы для пользовательских типов. Для бинарного оператора по крайней мере один из операндов должен иметь определенный пользователем тип.

Из стандарта C++ 20 (12.4.2.3 Операторы в выражениях)

2 If either operand has a type that is a class or an enumeration, a user-defined operator function can be declared that implements this operator or a user-defined conversion can be necessary to convert the operand to a type that is appropriate for a built-in operator. In this case, overload resolution is used to determine which operator function or built-in operator is to be invoked to implement the operator. Therefore, the operator notation is first transformed to the equivalent function-call notation as summarized in Table 15 (where @ denotes one of the operators covered in the specified subclause). However, the operands are sequenced in the order prescribed for the built-in operator (7.6).

Спасибо. Нужно ли писать две функции для случая где 3*x и случая x*3 или будет достаточно одной функции. Я только что попробовал, и кажется, что одной функции достаточно, но всегда хорошо спросить.

Shinobi San 17.05.2022 18:27

@ShinobiSan Поскольку оператор коммутативен, вам следует определить оба оператора.

Vlad from Moscow 17.05.2022 18:30

Я не очень понял, если он коммутативен, то одной функции должно быть достаточно, верно?

Shinobi San 17.05.2022 18:33

@ShinobiSan Недостаточно. То есть если вы перегрузите оператор для выражения 3*x, то для выражения x*3 компилятор выдаст ошибку, потому что для такого порядка аргументов этих типов такого оператора нет.

Vlad from Moscow 17.05.2022 18:35

Разрешение перегрузки С++ не предполагает, что * является коммутативным. (Это не всегда так.) Поэтому, если у вас есть operator*(const Rational&, int), но нет operator*(int, const Rational&), и вы пытаетесь написать 3 * someRational, компилятор не будет пытаться сказать: «Я не знаю, что это значит, но смогу ли я что-то сделать, если Я попробовал someRational * 3 вместо этого?»

Nathan Pierson 17.05.2022 18:36

@ShinobiSan Можно (и нужно) реализовать логику функции только один раз и ссылаться на эту реализацию также во второй функции, которая применяется для взаимозаменяемых параметров.

davidhigh 17.05.2022 18:43

Да, я бы посоветовал, чтобы в ответе Влада вторая функция просто читалась return r * x;

Nathan Pierson 17.05.2022 18:45

Другие вопросы по теме