

// Klasse für rationale Zahlen
class Rational
{
private:
  int num; // zähler
  int den; // nenner

public:

  Rational(int numerator = 0, int denominator = 1)
    : num(numerator), den(denominator)
  {
  }

  // Zuweisungsoperator gibt Referenz auf das Objekt selbst zurück um 
  // verkettete Zuweisung zu ermöglichen (a = b = c = ...)
  Rational& operator =(const Rational& rhs)
  {
    num = rhs.num;
    den = rhs.den;
    return *this;
  }

  // Vergleichsoperator
  bool operator ==(const Rational& rhs) const
  {
    return num == rhs.num && den == rhs.den;
  }

  // Zuweisung durch Addition gibt ebenfalls das Objekt zurück um Verkettung zu ermöglichen
  Rational& operator +=(const Rational& rhs)
  {
    num *= rhs.den;
    num += rhs.num * den;
    den *= rhs.den;
    return *this;
  }

  // unärers - (Negation)
  Rational operator -() const
  {
    return Rational(-num, den);
  }


  Rational operator +(const Rational& rhs) const
  {
    return Rational(num * rhs.den + den * rhs.num, den * rhs.den);
  }

  // Alternativ: Implementieren von + unter Verwendung von +=
  // Vermeidet Codeduplizierung und sorgt für Konsistenz
  //
  // Rational operator +(const Rational& rhs) const
  // {
  //   return Rational(*this) += rhs;
  // }



  // Operatoren die keine Memberfunktionen sind, sind in dem Fall als friend deklariert
  // um auf die privaten Elemente zugreifen zu können

  friend Rational operator *(const Rational& lhs, const Rational& rhs);
  {
    // Eine friend Funktion kann auch in der Klasse definiert werden
    return Rational(lhs.num * rhs.num, lhs.den * rhs.den);
  }

  friend std::ostream& operator <<(std::ostream& out, const Rational& r);

};


// Eigener stream-ouput-operator erlaubt es Rational Objekte auf std::ostream (z.B. cout) auszugeben.
// Definiert als freie Funktion, gibt wieder Objekt zurück um Verketten zu erlauben
std::ostream& operator <<(std::ostream& out, const Rational& r)
{
  out << r.num << " / " << r.den;
  return out;
}
