Создание cout ‹‹ obj1 + obj2 ‹‹ endl; Работа

Итак, я получил перегрузку оператора внутри класса, работающую для obj1 + obj2:

fraction operator+ (fraction op);

Точно так же cout ‹‹ obj работает путем перегрузки оператора, перегружающего ostream:

ostream& operator<< (ostream& os, fraction& frac);

Однако, если я попытаюсь совместить эти две вещи, все рухнет.

fraction.cpp:77:27: error: no match for ‘operator<<’ in 
‘std::operator<< [with _Traits = std::char_traits<char>]((* & std::cout), ((const char*)"Sum: ")) 
<< f1.fraction::operator+(f2)’

Вот код:

#include <iostream>
using namespace std;

class fraction
{
    private:
        int n, d;

    public:
        fraction ()
        {
            this->n = 1;
            this->d = 0;
        }

        fraction (int n, int d)
        {
            this->n = n;
            this->d = d;
        }

        int getNumerator ()
        {
            return n;
        }

        int getDenominator ()
        {
            return d;
        }

        fraction operator+ (fraction op)
        {
            return *(new fraction(this->n*op.d + op.n*this->d, this->d*op.d));
        }

        fraction operator- (fraction op)
        {

            return *(new fraction(this->n*op.d - op.n*this->d, this->d*op.d));
        }

        fraction operator* (fraction op)
        {
            return *(new fraction(this->n*op.n, this->d*op.d));
        }

        fraction operator/ (fraction op)
        {
            return *(new fraction(this->n*op.d, this->d*op.n));
        }
};

ostream& operator<< (ostream& os, fraction& frac)
{
    int n = frac.getNumerator();
    int d = frac.getDenominator();

    if(d == 0 && n == 0)
        os << "NaN";
    else if(d == 0 && n != 0)
        os << "Inf";
    else if(d == 1)
        os << n;
    else
        os << n << "/" << d;
}

int main ()
{
    fraction f1(2, 3);
    fraction f2(1, 3);

    cout << f1 << " " << f2 << endl;

    /*
    cout << "Sum: " << f1+f2 << endl;
    cout << "Difference: " << f1-f2 << endl;
    cout << "Product: " << f1*f2 << endl;
    cout << "Quotient: " << f1/f2 << endl;
    */

    return 0;
}

Помощь. Д:


person peteykun    schedule 29.07.2013    source источник
comment
Ты теряешь память как сумасшедший! Замените return *(new fraction(...)); на return fraction(...);.   -  person BoBTFish    schedule 29.07.2013
comment
Прекратите использовать new. Возможно, вы избавитесь от своего текущего учебного материала в пользу достойного.   -  person R. Martinho Fernandes    schedule 29.07.2013
comment
Не делайте return *(new T()), если вы пытаетесь получить объект, просто сделайте return T().   -  person 0x499602D2    schedule 29.07.2013
comment
Ваш ostream& operator<< не возвращает os.   -  person Rapptz    schedule 29.07.2013
comment
C++ это не Java. Как указывали другие, это течет, как лодка с корпусом-ширмой-дверью.   -  person WhozCraig    schedule 29.07.2013
comment
Некоторые другие комментарии: обычно я ожидаю, что fraction::fraction( int n, int d = 1 ) получит неявные преобразования из int. В этом случае operator+ и др. не должны быть членами; обычным соглашением было бы определение operator+= et al. как члены, а затем operator+ как свободную функцию, используя += в своей реализации. Если у вас есть неявное преобразование и operator+ является членом, fraction( 1, 2 ) + 3 работает, а 1 + fraction( 2, 3 ) — нет.   -  person James Kanze    schedule 29.07.2013
comment
Спасибо, ребята, просто попытаюсь сначала изучить некоторые уникальные функции C++ вместо того, чтобы перестраховаться с помощью метода .display(). Как вы понимаете, я знаком с C и Java. Все еще жду отправки своей копии C++ Primer.   -  person peteykun    schedule 29.07.2013


Ответы (1)


Непосредственная проблема в том, что

ostream& operator<< (ostream& os, fraction& frac)

не примет временную ссылку, потому что frac не является ссылкой const — измените ее на

ostream& operator<< (ostream& os, const fraction& frac)

operator+ между двумя дробями вернет временное значение, которое не может быть привязано к ссылке, отличной от const.

В следующих случаях также имеет место очень серьезная утечка памяти:

fraction operator+ (fraction )
{
   return *(new fraction(this->n*op.d + op.n*this->d, this->d*op.d)); 
}

new вернет динамически размещенный объект, который вы затем скопируете и вернете из функции.

Просто сделайте это, как большинство людей:

fraction operator+ (const fraction& op) const
{
   return fraction(this->n*op.d + op.n*this->d, this->d*op.d); 
}

(обратите внимание на две дополнительные константы и передачу по ссылке)

person Luchian Grigore    schedule 29.07.2013
comment
Это насущная проблема, но вам, вероятно, следует также указать, что operator+ и др. должен быть const, и что по обычному соглашению все аргументы fraction будут передаваться по ссылке на const (хотя это, вероятно, не имеет значения для этого класса). - person James Kanze; 29.07.2013
comment
Вероятно, вам следует упомянуть, что его потоковый оператор ничего не возвращает. - person Rapptz; 29.07.2013
comment
Что касается «Просто делай, как большинство людей»: я не знаю никого, кто сделал бы operator+ членом. В большинстве случаев вы просто наследуете что-то вроде ArithmeticOperators<fraction> и получаете это бесплатно. Если нет, то обычно это бесплатная функция, использующая += в своей реализации. (Но, конечно, ваша версия тоже вполне хороша, и для такого простого класса, может быть, даже предпочтительнее.) - person James Kanze; 29.07.2013
comment
Я делаю это членом, поскольку я не знал ничего другого. Я никогда не использовал язык, который дает вам так много способов сделать одно и то же, и большинство из них большую часть времени ошибочны. - person Neil Kirk; 29.07.2013
comment
@NeilKirk Не было сказано более правдивых слов, чем последнее предложение в вашем предыдущем комментарии, за исключением того, что по определению что-то неправильное - это не способ что-то сделать. C++ не прост. Но у вас здесь есть огромное множество людей, которые помогут вам, если вы действительно приложите к этому усилия на своей стороне. Выплата того стоит, так что придерживайтесь ее. - person WhozCraig; 29.07.2013
comment
@NeilKirk В Perl есть несколько способов сделать это. В C++ определение количества способов сделать что-либо является неопределенным поведением. - person Yakk - Adam Nevraumont; 29.07.2013