virtuelle Operatorfunktion



  • Hey Leute,

    ich habe eine Aufgabe zu virtuellen Operatorfunktionen mit drei Antwortmöglichkeiten, wovon
    eine richtig ist:

    "Angenommen, die Operatorfunktion += ist in einer Basisklasse Base als virtuell definiert. Die Klasse
    Derived entsteht aus Base durch public-Vererbung und stellt lediglich folgende Operatorfunktion zur
    Verfügung:

    Derived& operator+=(const Base& b;
    

    Außerdem ist eine globale Funktion add() wie folgt definiert:

    void add(Base& b1, const Base& b2)
    {
       b1 += b2;
    }
    

    Welche Version der Operatorfunktion += wird in der Funktion add() aufgerufen, wenn als
    erstes Argument ein Objekt der Klasse Base und als zweites Argument ein Objekt der Klasse
    Derived übergeben werden?

    a.) Die in der Basisklasse Base definierte Operatorfunktion
    b.) Die in der abgeleiteten Klasse Derived definierte Operatorfunktion
    c.) Beim Aufruf liefert der Compiler eine Fehlermeldung

    Welche der Möglichkeiten ist richtig und warum? Vielen Dank!


  • Mod

    Überladenen Operatoren haben keinerlei Sonderregeln, a += b ist äquivalent zu a.operator+=(b). Damit gelten die üblichen Regeln zur Auflösung von virtuellen und überladenen Funktionen. Was nicht unbedingt heißt, dass das einfach oder intuitiv ist, aber es ist strikt geregelt.

    Dein Rätsel kann ich damit aber nicht lösen, denn mir ist unklar, wo da überhaupt das Rätsel ist. Du erwähnst nur eine Funktion operator+=. Wenn die Beschreibung so richtig ist, dann ist doch klar, dass die genommen wird.



  • @SeppJ sagte in virtuelle Operatorfunktion:

    Du erwähnst nur eine Funktion operator+=

    Aufgrund der Aufgabenstellung gibt es wohl 2: In Base und in Derived.

    @C-Sepp :

    @SeppJ sagte in virtuelle Operatorfunktion:

    Damit gelten die üblichen Regeln zur Auflösung von virtuellen und überladenen Funktionen



  • @SeppJ sagte in virtuelle Operatorfunktion:

    Was nicht unbedingt heißt, dass das einfach oder intuitiv ist, aber es ist strikt geregelt.

    Ich würde vorschlagen, dann lieber die Operatoren NICHT virtual zu machen. Stattdessen, wenn man das braucht, im Operator einfach die virtuelle Funktion aufrufen. Ich würde Operator-Funktionen in der Regel so kurz und einfach wie möglich halten - bei komplxeren Dingen dann eben eine spezielle Member-Funktion aufrufen, sodass die Operator-Funktion selbst ein Einzeiler ist.



  • @wob sagte in virtuelle Operatorfunktion:

    Ich würde vorschlagen, dann lieber die Operatoren NICHT virtual zu machen. Stattdessen, wenn man das braucht, im Operator einfach die virtuelle Funktion aufrufen

    Ich würde überhaupt nichts virtuell machen. += sollte nur für 2 genau gleiche Typen existieren.



  • Antwort a ist laut Buch richtig. Also ist das erste Argument entscheidend für den Aufruf der Operatorfunktion?


  • Mod

    @Jockelx sagte in virtuelle Operatorfunktion:

    @wob sagte in virtuelle Operatorfunktion:

    Ich würde vorschlagen, dann lieber die Operatoren NICHT virtual zu machen. Stattdessen, wenn man das braucht, im Operator einfach die virtuelle Funktion aufrufen

    Ich würde überhaupt nichts virtuell machen. += sollte nur für 2 genau gleiche Typen existieren.

    Also ich habe nichts dagegen, dass man an einen String einen char heran addieren kann.



  • @C-Sepp sagte in virtuelle Operatorfunktion:

    Antwort a ist laut Buch richtig. Also ist das erste Argument entscheidend für den Aufruf der Operatorfunktion?

    @SeppJ hat doch schon geschrieben:

    Überladenen Operatoren haben keinerlei Sonderregeln, a += b ist äquivalent zu a.operator+=(b).

    Welches Objekt ist bei a.operator+=(b) ausschlaggebend dafür welche Funktion aufgerufen wird, a oder b?



  • Das sollte a sein.



  • @SeppJ sagte in virtuelle Operatorfunktion:

    Ich würde überhaupt nichts virtuell machen. += sollte nur für 2 genau gleiche Typen existieren.

    Also ich habe nichts dagegen, dass man an einen String einen char heran addieren kann.

    Und ich denke da an Vektor += Skalar oder Matrix *= Skalar. Sogar beim "echten Rechnen", wo + auch "addieren" und * multiplizieren bedeutet, will man das also erlauben 🙂

    Bei meinem ursprünglichen Beitrag dachte ich auch an den ostream& operator<<(ostream& os, const MeinTypBasisKlasse& mt), den ich öfter mal mit return mt.virtual_print_to_stream_function(os); implementiert habe (man will ja hier die virtuell-Eigenschaft für die Variable mt des eigenen Typs haben - ob ostream.operator<< virtuell ist oder nicht, ist mir erstmal wumpe).



  • @SeppJ sagte in virtuelle Operatorfunktion:

    Also ich habe nichts dagegen, dass man an einen String einen char heran addieren kann.

    @wob sagte in virtuelle Operatorfunktion:

    Und ich denke da an Vektor += Skalar oder Matrix *= Skalar. Sogar beim "echten Rechnen", wo + auch "addieren" und * multiplizieren bedeutet, will man das also erlauben

    Ja, ich habe mich blöd/falsch ausgedrückt, aber ich dachte im Kontext wäre klar, was ich meine. Eure Beispiele sind ja alle nicht mit Hilfe eines virtuellen Operators definiert worden.



  • @wob sagte in virtuelle Operatorfunktion:

    Bei meinem ursprünglichen Beitrag dachte ich auch an den ostream& operator<<(ostream& os, const MeinTypBasisKlasse& mt), den ich öfter mal mit return mt.virtual_print_to_stream_function(os); implementiert habe

    Das ist was anderes, da ist ja nur eine Klasse beteiligt. Der virtuelle operator muss aber irgendwie etwas sinnvolles definieren, für alle Kombinationen irgendwelcher Ableitungen. Und das geht dann auch nur mit gecaste.



  • Dementsprechend wird dann also, wenn zwei Objekte vom Typ Derived übergeben werden, die Operatorfunktion in Derived aufgerufen und einmal die Derived übergeben und von Derivd in Base konvertiert?


  • Mod

    Du hast doch überall Referenzen. Hier wird nirgendwo ein Objekt konvertiert, gespliced, oder sonstwie umgewandelt.



  • Also In meinen Buch gibt es ein kleines Kapitel: "Konvertierung in Referenzen auf Basisklassen".
    Darin steht: Beim Arbeiten mit Referenzen ist eine analoge Situation gegeben. Eine Referenz vom Typ "Referenz auf Basisklasse" kann auf ein Objekt einer abgeleiteten Klasse verweisen. Die Referenz stellt dann nur den Basisnateil dar.


  • Mod

    Das ist korrekt.



  • @C-Sepp
    Der Typ wird doch nur benutzt, um die richtig Überladung für den Funktionsaufruf zu finden.



  • Und warum wird dann in dem Fall, dass zwei Derived-Objekte übergeben werden und die "passendste" Überladung ausgewählt wird, nichts konvertiert?


  • Mod

    @C-Sepp sagte in virtuelle Operatorfunktion:

    Und warum wird dann in dem Fall, dass zwei Derived-Objekte übergeben werden und die "passendste" Überladung ausgewählt wird, nichts konvertiert?

    @SeppJ sagte in virtuelle Operatorfunktion:

    Du hast doch überall Referenzen. Hier wird nirgendwo ein Objekt konvertiert, gespliced, oder sonstwie umgewandelt.



  • @C-Sepp sagte in virtuelle Operatorfunktion:

    Die Referenz stellt dann nur den Basisnateil dar.

    Ich finde diesen Satz verwirrend at best. Eine Referenz referenziert immer ein Objekt, ich weiß nicht, was hier mit "stellt dann nur den Basisanteil dar." gemeint ist. Die Referenz zeigt auf das ganze, echte, möglicherweise abgeleitete Objekt.

    Stelle dir eine Referenz wie ein Pointer vor, der immer initialisiert werden muss und dem du nie nullptr zuweisen kannst - und bei dem der -> sozusagen fest eingebaut ist.


Anmelden zum Antworten