friend Funktionen anderer Klassen



  • Improve the Lobby class from the Game Lobby program by writing a friend function of the Player class that allows a Player object to be sent to cout. Next, update the function that allows a Lobby object to be sent to cout so that it uses your new function for sending a Player object to cout.

    Steht doch gar nicht drinnen, dass das ne Member-Funktion sein soll.
    Zur Info: Zum Interface einer Klasse gehören auch freie Funktionen, die auf der jeweiligen Klasse arbeiten! Somit ist auch eine freie Funktionen ein "improvement" deiner Klasse.

    TestGuest schrieb:

    PS: Wenn man Code mit copy&paste einfügt, wird er nach der ersten Vorschau mit vielen Leerzeilen versehen. Wie verhindert man das? Mein Editor ist gedit.

    Das liegt an der Editorkomonente die dein Browser verwendet. Du hast wahrscheinlich da Tabs im Code. Die werden beim Pasten in Leerzeichen umgewandelt. Und die Editorkomponente wird da wohl gaaanz viele reinbauen (8 Stück, kann das sein?).



  • Erstmal danke an Alle! Das heisst also, dass die Überladung ausserhalb der Klassendefinition und fast ebenso wie die Überladung fürs Lobby Objekt implementiert wird. Hier die entsprechenden Codefragmente:

    class Lobby
    {
        friend ostream& operator<<(ostream& os, const Lobby& aLobby);
    
        // Hinzu
        friend ostream& operator<<(ostream& os, const Player& p);
    ...
    
    };
    
    // Hinzu
    ostream& operator<<(ostream& os, const Player& p)
    {
        os << p.GetName();
        return os;
    }
    
    void Lobby::AddPlayer()
    {
        //create a new player node
        cout << "Please enter the name of the new player: ";
        string name;
        cin >> name;
        Player* pNewPlayer = new Player(name);
    
        ...
    
        cout << pNewPlayer;
        // cout << *pNewPlayer;
    }
    

    Bei den letzten Zeilen bekomme ich nun im ersten Fall (28) lediglich die Adresse des Objektes, im zweiten Fall (29) wieder eine Reihe von Fehlermeldungen. Ich hätte gedacht, dass die erste Zeile funktionieren muss, da doch eine Referenz auch nur ein Zeiger auf ein Objekt ist?!



  • Die Funktion muss ein Friend von Player sein, nicht von Lobby. Mit Lobby hat sie nichts am Hut.



  • MFK schrieb:

    Die Funktion muss ein Friend von Player sein, nicht von Lobby. Mit Lobby hat sie nichts am Hut.

    Oh natürlich! Das fällt nun unter die Rubrik Flüchtigkeitsfehler. 😃
    So funktioniert es jetzt, jedoch mit:

    cout << *pNewPlayer;
    

    Klar, dass der Zeigerinhalt die Referenz auf das Objekt darstellt. Aber die ist doch auch nur ein Zeiger, oder? Also wäre der Zeiger pNewPlayer ein Zeiger auf einen Zeiger, richtig?



  • TestGuest schrieb:

    Klar, dass der Zeigerinhalt die Referenz auf das Objekt darstellt. Aber die ist doch auch nur ein Zeiger, oder? Also wäre der Zeiger pNewPlayer ein Zeiger auf einen Zeiger, richtig?

    Lös dich bitte von der Vorstellung, dass eine Referenz "auch nur ein Zeiger" ist. Es stimmt einfach nicht.



  • MFK schrieb:

    Lös dich bitte von der Vorstellung, dass eine Referenz "auch nur ein Zeiger" ist. Es stimmt einfach nicht.

    Ok, dann nehme ich das so hin. Kannst Du den Unterschied illustrieren? Weder in dem Buch, noch in Tutorials wird mir richtig klar, wo der Unterschied liegt, bzw. inwieweit beides austauschbar ist (also, kann man z.B. einen Zeiger übergeben, wo eine Referenz verlangt wird, usw.)?!

    Ich habe auch Probleme mit den Konventionen von Zeigern. Im Buch steht folgendes:

    int score = 100;
    int* const pScore = &score;
    

    ist ein Konstanter Zeiger. Weiterhin

    const int* pNumber = &score;
    

    ist ein Zeiger auf eine Konstante. Und dann gibt es halt noch konstante Zeiger auf eine Konstante. In einem Tutorial hier aus dem Forum (nämlich aus cpp_mta_rwthaa.pdf) ist:

    char const *p:
    

    ein Zeiger auf eine Konstante, und:

    char w;
    char * const p = w;
    

    ein konstanter Zeiger. Gibt es eine Fausregel, wie man sich die unterschiedlichen Schreibweisen einprägen kann?



  • TestGuest schrieb:

    Kannst Du den Unterschied illustrieren? Weder in dem Buch, noch in Tutorials wird mir richtig klar, wo der Unterschied liegt, bzw. inwieweit beides austauschbar ist (also, kann man z.B. einen Zeiger übergeben, wo eine Referenz verlangt wird, usw.)?!

    Austauschbar sind also nicht Zeiger und Referenz, sondern Referenz und Objekt. Zeiger sind etwas komplett anderes.

    Ein Zeiger ist ein eigenständiges Objekt, das einen Verweis auf ein anderes Objekt speichern kann (aber nicht muss). Auf welches Objekt ein Zeiger verweist, kann man ändern (daher die Unterscheidung zwischen konstantem Zeiger und Zeiger auf Konstante). Ein Zeiger kann Null sein, also auf nichts zeigen. Einen Zeiger behandelst du grundsätzlich anders als das Objekt, auf das es zeigt: Wenn du ihn übergeben willst, wo Objekt oder Referenz verlangt sind, musst du ihn dereferenzieren, um auf die Member zuzugreifen, brauchst du -> statt . usw.

    Eine Referenz ist ein neuer Name für ein bestehendes Objekt. Wenn du ein Objekt A hast und eine Referenz B dafür anlegst, sagst du dem Compiler: "Wann immer ich jetzt B sage, meine ich Objekt A". Die Referenz ist also insofern kein eigenständiges Objekt, als du sie nicht beeinflussen kannst. Alles, was du mit der Referenz machst, machst du mit dem Objekt, für das sie steht. Weder kann eine Referenz auf ein anderes Objekt "umgebogen" werden, noch kann sie auf nichts zeigen (es sei denn, die Referenz lebt länger als das Objekt, für das sie steht, aber das ist ein Programmierfehler). Du behandelst eine Referenz im Code genauso wie das eigentliche Objekt.

    TestGuest schrieb:

    Ich habe auch Probleme mit den Konventionen von Zeigern.

    Einfache Faustregel: Das const bezieht sich immer auf das, was links davon steht. Wenn das const ganz links steht, bezieht es sich auf das, was rechts davon steht. Folgende Deklarationen sind also gleichwertig:

    const int* p;
    int const* p;
    

    Und ob du vor oder nach dem Stern Leerzeichen machst, ist inhaltlich völlig egal.



  • MFK schrieb:

    Austauschbar sind also nicht Zeiger und Referenz, sondern Referenz und Objekt. Zeiger sind etwas komplett anderes.

    Ich wollte ein entsprechends Beispiel suchen, habe aber festgestellt, dass ich Referenzoperator (string& obj) und Adressoperator (int* a = &b) verwechselt hatte.

    MFK schrieb:

    Wenn du ihn übergeben willst, wo Objekt oder Referenz verlangt sind, musst du ihn dereferenzieren, um auf die Member zuzugreifen, brauchst du -> statt . usw.

    Das ist klar, oder auch (*pointer).member

    MFK schrieb:

    Einfache Faustregel: Das const bezieht sich immer auf das, was links davon steht. Wenn das const ganz links steht, bezieht es sich auf das, was rechts davon steht. Folgende Deklarationen sind also gleichwertig:

    const int* p;
    int const* p;
    

    Und ob du vor oder nach dem Stern Leerzeichen machst, ist inhaltlich völlig egal.

    Folgendes Zeilen sind laut Buch unterschiedlich:

    int* const p = &i;
    const int* p;
    const int* const p = &i;
    

    Im ersten Fall sollt es sich um einen konstanten Zeiger handeln, im zweiten Fall um einen Zeiger auf eine Konstante, letzteres ein konstanter Zeiger auf eine Konstante. Nach Deiner Erklärung würde sich also das const immer auf int* beziehen, im letzten Fall sogar doppelt. Das habe ich nicht verstanden.

    PS: Was war denn mit dem Forum los?



  • TestGuest schrieb:

    Nach Deiner Erklärung würde sich also das const immer auf int* beziehen, im letzten Fall sogar doppelt. Das habe ich nicht verstanden.

    Das const bezieht sich niemals auf int*. Du musst int und * getrennt betrachten. Du kannst das const auch dazwischen schreiben:

    int* const p = &i;       // const bezieht sich auf *
    const int* p;            // const bezieht sich auf int
    int const* p;            // const bezieht sich auf int
    const int* const p = &i; // ein const für int, eins für *
    int const * const p = &i;// ein const für int, eins für *
    


  • MFK schrieb:

    Das const bezieht sich niemals auf int*. Du musst int und * getrennt betrachten. Du kannst das const auch dazwischen schreiben:

    int* const p = &i;       // const bezieht sich auf *
    const int* p;            // const bezieht sich auf int
    int const* p;            // const bezieht sich auf int
    const int* const p = &i; // ein const für int, eins für *
    int const * const p = &i;// ein const für int, eins für *
    

    Vielen Dank, das ist so absolut verständlich! Bei der Gelegenheit hab ich mich gerade mal offiziell angemeldet.

    Schönen Gruß


Anmelden zum Antworten