Output Streamingoperator überladen ( operator<< )



  • Hallo,

    ich würde gerne den operator<< in meinen abgeleiteten Klassen überladen.

    Also:
    ich habe eine Basisklasse.
    Davon habe ich zwei Klassen abgeleitet: Klasse1 und Klass2.

    Nun habe ich den Streamingoperator überladen (erstmal in der Basisklasse):

    friend ostream & operator<<(ostream& output, const Student& curObj) {
    output<<endl;
    return output;}
    

    Ich habe nun eine STL List list<Basisklasse *> in denen ich Zeiger auf Klase1 und Klasse2 verwalte.

    Mein Problem ist: Wie kann ich den operator<< in den abgeleiteten Klassen implementieren ?

    eigentliche Idee:
    Operator<< in der Basisklasse überladen und anschließend in den abgeleiteten Klassen überschreiben. Geht aber nicht, weil ich hier kein virtual flag verwendet darf.
    Bzw. ist die Grundidee wohl schon falsche ?! 😞

    Meine Lösung ist nun, dass ich nur in der Basisklasse den operator<< überschreibe und dort die Ausgabe mache.
    Funktioniert, aber ich würde gerne wissen, wie ich das umsetze, dass ich den operator<< in den abgeleiteten Klassen überlade und das mit der oben genannten Liste funktioniert.

    Hoffe mein Problem ist verständlich.

    Vielen Dank für Eure Hilfe.

    Gruß Manuel



  • Kosi.h:19: error: redefinition of `std::ostream& operator<<(std::ostream&, const Student&)'

    Ist die Fehlermeldung, wenn ich den Streamingoperator nur in den abgeleiteten Klassen implementiere.



  • Moinuel schrieb:

    Mein Problem ist: Wie kann ich den operator<< in den abgeleiteten Klassen implementieren ?

    eigentliche Idee:
    Operator<< in der Basisklasse überladen und anschließend in den abgeleiteten Klassen überschreiben. Geht aber nicht, weil ich hier kein virtual flag verwendet darf.
    Bzw. ist die Grundidee wohl schon falsche ?! 😞

    Hallo Manuel,

    Deine Grundidee ist richtig. Der Streaming-Operator ist aber eine Funktion, überschreiben nützt hier nichts. Was Du überschreiben kannst, ist eine virtual Memberfunktion, also ruft man diese in der Streaming-Funktion auf.
    Im Prinzip:

    class Student // Basisklasse
    {
        friend std::ostream& operator<<( std::ostream& out, const Student& s )
        {
             s.print( out );
             return out;
        }
    protected:
        virtual void print( std::ostream& out ) const =0; 
    };
    class Klasse1 : public Student
    {
    protected:
        virtual void print( std::ostream& out ) const
        {
            // hier steht der Code zur Ausgabe von Klasse1 nach 'out'
        }
    };
    class Klasse2 .. // genauso wie Klasse1
    

    Gruß
    Werner



  • rufe im operator<< für die basisklasse eine virtuelle funktion auf, die das verhalten von print für einen ostream implementiert, wenn du dynamisch entscheiden willst, was ausgegeben werden soll.



  • oops, zu spät ^^



  • Hey,
    danke für die schnelle Hilfe.
    Da lag ich ja garnicht mal so daneben.

    Danke nochmal.

    Gruß Manuel



  • Da operator<< eine freie Funktion ist, kannst du natürlich kein virtual verwenden.

    Moinuel schrieb:

    Meine Lösung ist nun, dass ich nur in der Basisklasse den operator<< überschreibe und dort die Ausgabe mache.

    Wenn du nur für die Basisklasse operator<< hast, dann kannst du doch immer nur die Datenelemente der Basisklasse ausgeben. Verstehe deshalb nicht, wieso das eine Lösung sein soll?

    Du willst doch immer die Datenelemente des Objekts ausgeben, das sich hinter Basisklasse* verbirgt, oder? Wieso machst du dann keine virtual output Funktion?

    edit: viel zu spät.



  • @Werner Salomon: Wieso protected ?



  • Gugelmoser schrieb:

    @Werner Salomon: Wieso protected ?

    Weil man die Methode von aussen nicht direkt aufrufen koennen soll (man soll ja den <<-Operator verwenden), die Methode aber in den Unterklassen sichtbar sein muss, damit sie ueberladen werden kann.
    Und protected erfuellt genau diese Anforderungen.



  • icarus2 schrieb:

    Gugelmoser schrieb:

    @Werner Salomon: Wieso protected ?

    Weil man die Methode von aussen nicht direkt aufrufen koennen soll (man soll ja den <<-Operator verwenden), die Methode aber in den Unterklassen sichtbar sein muss, damit sie ueberladen werden kann.
    Und protected erfuellt genau diese Anforderungen.

    Ich wollte damit sagen, dass es auch mit private funktioniert. (gcc 4.6.1)



  • Zum Überschreiben reicht private aus, protected ist nur nötig, wenn die Funktion von der abgeleiteten Klasse aus aufgerufen können werden soll.



  • Gugelmoser schrieb:

    Ich wollte damit sagen, dass es auch mit private funktioniert. (gcc 4.6.1)

    Stimmt. Ich wusste gar nicht mehr, dass man private Methoden ueberschreiben kann 😕


Anmelden zum Antworten