1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies. Weitere Informationen

Problem beim Überladen des << - Operators

Dieses Thema im Forum "C/C++" wurde erstellt von Reyme, 6. April 2012.

  1. Reyme

    Reyme Grünschnabel

    Hallo :)
    Ich hab mal wieder ein Problem:
    Da in meinem "C++-Programmierer" gerade das Überladen von Operatoren durchgenommen wird, dachte ich mir, ich programmiere eine kleine Klasse für rationale Zahlen. Hier ein kleiner Codeausschnitt:

    Code (Text):
    1.  
    2. //rational.h
    3.  
    4. #ifndef RATIONAL_H
    5. #define RATIONAL_H
    6.  
    7. class rational {
    8.        [...]
    9. }
    10.  
    11. [...]
    12.  
    13. rational operator+ (rational& r1, rational& r2);
    14. std::ostream& operator<< (std::ostream& os, rational& r);
    15.  
    16. #endif //RATIONAL_H
    17.  
    Code (Text):
    1.  
    2. //rational.cpp
    3.  
    4. #include "rational.h"
    5.  
    6. rational operator+ (rational& r1, rational& r2) {
    7.      [...]
    8. }
    9.  
    10. std::ostream& operator<< (ostream& os, rational& r) {
    11.     return os << r.getzaehler() << " / " << r.getnenner();
    12. }
    13.  
    Das Überladen des +-Operators funktioniert, aber beim compilieren des <<-Operators erhalte ich die Fehlermeldung
    :(

    PS: Wenn das etwas helfen sollte: Ich arbeite mit Code::Blocks

    Wäre schön wenn jemand eine Antwort für mich hätte :)

    Oh ich habe mich verschrieben :)

    bei rational.cpp das "return" weglassen :)
  2. sheel

    sheel Mod # I love Asm Moderator

    Hi

    da gehört aber ein return.

    In welcher Zeile wird er Fehler gezeigt?
    ostream ist dreinmal mit std:: und einmal ohne.
  3. Reyme

    Reyme Grünschnabel

    Das std hab ich jetzt noch ergänzt, die Fehlermeldung bleibt aber :(

    Die Fehlermeldung bezieht sich auf Z. 13 von rational.h
  4. sheel

    sheel Mod # I love Asm Moderator

    Da Teile rausgenommen sind: Was ist bei dir Zeile 13?
    Komplette Datei wäre sowieso hilfreich.
  5. Endurion

    Endurion Erfahrenes Mitglied

    Die Fehlermeldung sagt ofstream, überall sonst schreibst du aber ostream. Ist da ein f reingerutscht?
  6. Reyme

    Reyme Grünschnabel

    Nein, da ist mir bei der Fehlermeldung ein f reingerutscht :)

    Z. 13 bezieht sich auf den Code oben

    Hier aber mal der komplette Code(weil er gewünscht ist):

    Code (Text):
    1. //rational.h
    2.  
    3. #ifndef RATIONAL_H
    4. #define RATIONAL_H
    5.  
    6. class rational {
    7.     public:
    8.         rational(int z, int n);
    9.         rational(rational& r);
    10.  
    11.         void setzaehler(int z);
    12.         void setnenner(int n);
    13.  
    14.         const int getzaehler();
    15.         const int getnenner();
    16.  
    17.         const double getwert();
    18.  
    19.         bool operator>= (rational& r);
    20.         bool operator<= (rational& r);
    21.         bool operator<  (rational& r);
    22.         bool operator>  (rational& r);
    23.         bool operator== (rational& r);
    24.  
    25.         rational& operator= (rational& r);
    26.     private:
    27.         int zaehler;
    28.         int nenner;
    29. };
    30.  
    31. inline rational::rational(int z = 0, int n = 0)
    32.     : zaehler(z), nenner(n) {};
    33.  
    34. inline rational::rational(rational& r)
    35.     : zaehler(r.zaehler), nenner(r.nenner) {};
    36.  
    37. inline void rational::setzaehler(int z) {
    38.     zaehler = z;
    39. }
    40.  
    41. inline void rational::setnenner(int n) {
    42.     nenner = n;
    43. }
    44.  
    45. inline const int rational::getnenner() {
    46.     return nenner;
    47. }
    48.  
    49. inline const int rational::getzaehler() {
    50.     return zaehler;
    51. }
    52.  
    53. inline const double rational::getwert() {
    54.     return static_cast<double> (zaehler) / static_cast<double>(nenner);
    55. }
    56.  
    57. rational operator+ (rational& r1, rational& r2);
    58. std::ostream& operator<< (std::ostream& os, rational& r);
    59.  
    60. #endif //RATIONAL_H
    61.  
    und

    Code (Text):
    1. //rational.cpp
    2.  
    3. #include "rational.h"
    4.  
    5. rational operator+ (rational& r1, rational& r2) {
    6.     rational temp(0, 0);
    7.     temp.setzaehler(r1.getzaehler() * r2.getnenner() + r2.getzaehler() * r1.getnenner());
    8.     temp.setnenner(r1.getnenner() * r2.getnenner());
    9.  
    10.     return temp;
    11. }
    12.  
    13. inline bool rational::operator>=(rational& r) {
    14.     return getwert() >= r.getwert();
    15. }
    16.  
    17. inline bool rational::operator<=(rational& r) {
    18.     return getwert() <= r.getwert();
    19. }
    20.  
    21. inline bool rational::operator< (rational& r) {
    22.     return getwert() < r.getwert();
    23. }
    24.  
    25. inline bool rational::operator> (rational& r) {
    26.     return getwert() > r.getwert();
    27. }
    28.  
    29. inline bool rational::operator== (rational& r) {
    30.     return getwert() == r.getwert();
    31. }
    32.  
    33. rational& rational::operator= (rational& r) {
    34.     zaehler = r.getzaehler();
    35.     nenner = r.getnenner();
    36.  
    37.     return *this;
    38. }
    39.  
    40. std::ostream& operator<< (std::ostream& os, rational& r) {
    41.     return os << r.getzaehler() << '/' << r.getnenner();
    42. }
    43.  
    Jetzt bezieht sich die Fehlermeldung auf Z. 58 der "rational.h" Datei :)
  7. deepthroat

    deepthroat Premium-User

    Hi.

    Wenn du std::eek:stream in einer Datei verwenden willst, mußt du natürlich auch die entsprechende Headerdatei einbinden welche diesen Typ deklariert. Da ist die Fehlermeldung doch eigentlich hinreichend deutlich... :confused:

    Übrigens ist "const" als Modifzierer bei Rückgabetypen unsinnig. Die get Methoden solltest du stattdessen als const markieren:
    Code (C++):
    1. // nicht so:
    2. const /* <-- hat keine Wirkung */ double getwert();
    3.  
    4. // sondern so:
    5. double getwert() const;
    Gruß
  8. Matthias Reitinger

    Matthias Reitinger ɐɯıǝɹ Premium-User

    Hallo,

    du hast vergessen, in rational.h den Header <ostream> einzubinden:

    Code (C++):
    1. #include <ostream>
    Grüße,
    Matthias

    \edit: Zu langsam…

    Um doch noch was Neues beizutragen: an allen Stellen in deinem Code, an denen du eine Referenz als Argument übergibst, kannst du genauso gut auch eine Const-Referenz übergeben. Du modifizierst die übergebenen Instanzen schließlich nicht. Ansonsten kannst du z.B. kein const rational addieren oder ausgeben.
    Zuletzt bearbeitet: 7. April 2012
  9. Reyme

    Reyme Grünschnabel

    Vielen Dank für die Hilfe :)
  10. Reyme

    Reyme Grünschnabel

    Aber wenn wir schonmal dabei sind über überladene Operatoren zu reden:

    Gibt es eigentlich eine feste Regel, wann man die Übergabe per Referenz oder per Wert verwendet oder muss man sich in jedem einzelnen Fall Gedanken dazu machen?
  11. ibafluss

    ibafluss Erfahrenes Mitglied

    Gedanken solltest du dir beim Programmieren immer machen ;)
    Aber beim Überladen von Operatoren kannst du die Variablen eigentlich immer per Referenz übergeben.
    Anders ist es beim Zurückgeben: Bei operator+() zum Beispiel musst du ein neues Objekt zurückgeben (du kannst in die übergebenen Parameter ja nicht das Ergebnis der Addition speichern). Also bei der Rückgabe solltest du die schon überlegen, was besser ist, bei der Übergabe eigentlich immer Referenz.

    Lg
  12. Reyme

    Reyme Grünschnabel

    Was ich dabei aber ein bisschen ärgerlich finde:

    ich kann bei dem Beispiel oben z.B nicht schreiben
    Code (Text):
    1.  
    2.  
    3. int main() {
    4.      rational r1(2, 5);
    5.      rational r2(3, 5);
    6.      
    7.      rational r3(r1 + r2);
    8. }
    9.  
    10.  
    , da der Konstruktor eine Referenz erwartet, bei der Addition aber ein Wert zurückgegeben wird :( . Ist aber insgesamt gesehen nicht schlimm, da man auch
    Code (Text):
    1.  
    2. rational r3;
    3. r3 = r1 + r2;
    4.  
    schreiben kann.

    Oder gibt es da noch eine andere Möglichkeit, mit der man das umgehen kann?
  13. sheel

    sheel Mod # I love Asm Moderator

    Das angesprochene Poblem ist auf die (älteren) Versionen vom Standart zurückzuführen,
    die keine R-Value-Referenzen erlauben/ermöglichen

    (L-Value/R-Value: Was bei einer Zuweisung (ohne Op-Überladung) links und rechts stehen kann.
    x=y
    x kann eine Variable sein
    y kann eine Variable oder ein Wert sein
    Du übergibst einen Wert, Referenzen gehen aber nur auf dem Compiler benannte Variablen)

    Das sollte inzwischen (aufgrund dem neuen C++-Standart ab gcc 4.3) unerstützt werden.
    Mal testen...

    edit: Also bei mir gehts mit den Rvalues wie erwartet.
  14. deepthroat

    deepthroat Premium-User

    Du sprichst vom Kopierkonstruktor. Dieser sollte immer eine konstante Referenz übergeben bekommen, das funktioniert dann nämlich auch mit temporären Objekten (also mit deinem Beispiel).

    Code (C++):
    1. class rational {
    2. ...
    3. public:
    4.   rational(const rational& other);
    5. };
    6.  
    7. ...
    8. rational c(a + b); // OK
    Das ist natürlich nicht wirklich optimal und bei deinem Code auch gar nicht möglich, da du keinen Standardkonstruktor definiert hast.

    Gruß

Diese Seite empfehlen