Przeciążenie operatora >>

0

Witam,

Mam problem z poniższym kodem, bo przy kompilacji na ekranie widzę ciągle pojawiający się napis:
Podaj liczbe rzeczywista:
Podaj liczbe rzeczywista:
Podaj liczbe rzeczywista:
itd.
Nie wiem w którym miejscu leży błąd. Proszę o pomoc.

#include <iostream>
using std::cout;
using std::cin;
class Complex
{
private:
    double normal;
    double imaginary;
public:
    Complex();
    Complex(double x, double y=0.0) : normal(x), imaginary(y){}
    Complex operator+(const Complex & Co) const;
    Complex operator-(const Complex & Co) const;
    Complex operator*(const Complex & Co) const;
    Complex operator*(double  n) const;
    Complex operator~() const;
    friend std::istream & operator>>(std::istream & is, const Complex & Co);
    friend std::ostream & operator<<(std::ostream & os, const Complex & Co);
};
int main()
{
    Complex a(3.0, 4.0);
    Complex c;
    cout<<"Podaj liczbe zespolona (k, aby zakonczyc):\n";
    while (cin>>c)
    {
        cout<<"c to "<<c<<'\n';
        cout<<"sprzezona z c to "<<~c<<'\n';
        cout<<"a to " <<a<<'\n';
        cout<<"a+c wynosi "<<a+c<<'\n';
        cout<<"a-c wynosi "<<a-c<<'\n';
        cout<<"a*c wynosi "<<a*c<<'\n';
        cout<<"2*c wynosi "<<c*a<<'\n';
        cout<<"Podaj liczbe zespolona (k, aby zakonczyc):\n" ;
    }
    cout<<"do widzenia";
    return 0;
}
Complex::Complex()
{
    normal = 0.0;
    imaginary = 0.0;
}
Complex Complex::operator+(const Complex & Co) const
{
    return Complex(normal + Co.normal, imaginary+ Co.imaginary);
}
Complex Complex::operator-(const Complex & Co) const
{
    return Complex(normal - Co.normal, imaginary - Co.imaginary);
}
Complex Complex::operator*(const Complex & Co) const
{
    return Complex(normal * Co.normal - imaginary * Co.imaginary, normal* Co.imaginary + imaginary* Co.normal);
}
Complex Complex::operator*(double n) const
{
    return Complex(normal * n, imaginary* n);
}
Complex Complex::operator~() const
{
    return Complex(normal, -imaginary);
}
std::istream & operator>>(std::istream & is, const Complex & Co)
{
    cout<<"Podaj liczbe rzeczywista: "<<std::endl;                            //problem w tym miejscu.``
    is>>Co.normal;
    cout<<"\nSkladowa urojona: ";
    is>>Co.imaginary;
    return is;
}
std::ostream & operator<<(std::ostream & os, const Complex & Co)
{
    using std::endl;
    os<<"("<<Co.normal<<", "<<Co.imaginary<<"i)"<<endl;
    return os;
}
1

Nie wiem na pierwszy rzut oka dlaczego się zapętla, ale używanie cout wewnątrz istream& operator>> na zalecaną praktykę nie wygląda, łagodnie mówiąc.

0

Usunąłem cout z tego miejsca, jednak problem się powtarza - tym razem nie mogę nic wpisać. Można wiedzieć czemu jest to błąd(cout w przeciążeniu >>?

6

Dobrze, że przygotowałeś MCVE, bo na początku myślałem, że to nie ma prawa się skompilować. A to jednak ciekawy przypadek związany z niechlujnym kodowaniem.

Complex(double x, double y=0.0) : normal(x), imaginary(y){}

Brak explicit oznacza tu, że funkcja przyjmująca Complex może zostać wywołana z parametrem double. Np. void foo(Complex const&)foo(6.0)

std::istream & operator>>(std::istream & is, const Complex & Co)

const przy Complex oznacza, że nie planujesz zapisu do tego obiektu. Co ważniejsze
is>>Co.normal; nie ma przeładowania realizujacego operator>>(ostream&, const double&). Ale z double, jak już wyżej wspomnieliśmy można utworzyć Complex. Wobec czego wywoływane jest kolejne przeładowanie, następne w kolejności najlepszości - operator>>(ostream&, const Complex&). A z niego... wróć 2 linie wyżej. Masz nieskończoną pętlę.

Wniosek:

  • używaj explicit konstruktory,
  • nie próbuj zapisać do const

Tutaj popełniłem posta na ten temat: https://dsp.krzaq.cc/post/304/jak-przeladowywac-operatory-w-mojej-klasie/

Jeszcze jedna rzecz - na szybko zauważyłem, że przeładowałeś operator ~ jako -. To będzie nieczytelne dla użytkowników klasy. Klasy biblioteczne (a Complex zdecydowanie taką jest) nie powinny przejawiać zaskakujących zachowań. Negacja logiczna to !, binarna to ~, a liczbowa to -.

0

Według debuggera, program whodzi w rekurencję dla funkcji:
std::istream & operator>>(std::istream & is, const Complex & Co)
Wychodzi na to, że przez przekazywanie przez const referencję, kompilator nieco inaczej zinterpretował funkcję, więc
w linii: is>>Co.normal; zamiast wołać std::istream& operator>>(std::istream&, float&) zawołał ponownie std::istream & operator>>(std::istream & is, const Complex & Co).
Nie wiem dlaczego wyszedł taki kod binarny. Liczyłem na błąd kompilatora, ale taki sam efekt jest dla g++ i clang++.
Błędna na pewno jest sygnatura funkcji, gdzie jako parametr przekazujesz const Complex&, a modyfikujesz obiekt. Dla std::istream & operator>>(std::istream & is, Complex & Co), funkcja działa zgodnie z oczekiwaniem.

0

Po usunięciu const wszystko działa poprawnie, dzięki

1 użytkowników online, w tym zalogowanych: 0, gości: 1