#cpp #перегрузка_операторов #операторы
Пишу класс рациональных чисел. Хочу перегрузить оператор сложения, чтобы можно было складывать с дробями целые числа. Всё получилось, но проблема в том что возможна запись <мой класс> = <мой класс> + <целое число> Если же я пишу так: <мой класс> = <целое число> + <мой класс> всё крашится: no match for 'operator+' (operand types are 'int' and 'Number') Вoт код в .h: class Number { public: Number(int numerator = 0, int denominator = 1); int getNumerator() {return this->numerator;} int getDenominator() {return this->denominator;} string toString(); // определяем арифметические действия дробей с дробями Number operator+ (Number &other); Number operator- (Number &other); Number operator* (Number &other); Number operator/ (Number &other); // определяем арифметические действия дробей с целыми числами Number operator+ (int i); protected: int numerator; // числитель int denominator; // знаменатель }; Код в .cpp: Number Number::operator+(int i) { Number res(i * this->denominator() + this->numerator(), this->denominator()); return res; }
Ответы
Ответ 1
Вот в том числе и по этой причине такие операторы рекомендуется реализовывать не методами класса, как у вас, а отдельными (дружественными) функциями. Вы реализовали именно оператор сложения, в котором целое является правым операндом. Реализовать оператор сложения для целого числа в качестве левого операнда методом класса невозможно в принципе. Его в любом случае придется реализовывать обычной функцией. Но тут на самом деле стоит сделать шаг назад и посмотреть на общий дизайн. Вам на самом деле вообще не нужно реализовывать операторы для сложения с целыми числами. Ваш класс Number уже обладает конвертирующим конструктором, который умеет преобразовывать целые числа в ваш Number. После этого ваши готовые операторы для операндов типа Number уже сами сделают все правильно. Для этого, однако необходимо 1) реализовать их обычными функциями, 2) не забыть о const в параметрах-ссылках, который у вас почему-то отсутствует. class Number { public: Number(int numerator = 0, int denominator = 1); // определяем арифметические действия дробей с дробями friend Number operator +(const Number &lhs, const Number &rhs); friend Number operator -(const Number &lhs, const Number &rhs); friend Number operator *(const Number &lhs, const Number &rhs); friend Number operator /(const Number &lhs, const Number &rhs); protected: // <- ??? int numerator; // числитель int denominator; // знаменатель }; Такой класс уже сам по себе будет поддерживать Number a(2, 3); Number b = a + 1; Number c = 25 + a; и ничего для этого дополнительно писать не надо. Если вам при этом захочется написать отдельные реализации для операций с обычными числами (например, в целях оптимизации) - вы можете это сделать. Но лучше это делать обычными функциями с двумя параметрами, как показано выше, а не методами класса.Ответ 2
#includeusing namespace std; struct Number { int numerator; // числитель int denominator; // знаменатель Number(int num = 0, int denom = 1) : numerator(num), denominator(denom) {} //... // определяем арифметические действия дробей с целыми числами Number operator+ (int i) { return Number(i * denominator + numerator, denominator); } friend Number operator +(const int i, const Number& N) { return Number(i * N.denominator + N.numerator, N.denominator); } friend ostream& operator <<(ostream& os, const Number& N) { os << N.numerator << " / " << N.denominator; return os; } }; int main() { Number test(4, 2); std::cout << 5 + test; return 0; // теперь все нормально! } просто оператор определите и еще можете при возвращении Number производить еще и сокращение дроби... и не нужно делать данные закрытыми, если вы всеравно обеспечиваете доступ ко всем данным! Если вам удобно, то вы можете не определить int + Number, но в кодах написать не 5 + Number, а Number(5) + Number...
Комментариев нет:
Отправить комментарий