[Gelöst] Designfrage - output operator für private member



  • Hallo zusammen,

    ich hab eine kleine Aufgabe einfach zum Spaß bearbeitet (sie sollte eigentlich wirklich trivial sein).

    Zuerst mal einen Name und ein Alter einlesen und ausgeben. Ok, baby einfach.
    Dann soll man das ganze wiederholen, indem man eine Reihe von (Name, Alter) Paaren in einer Klasse speichert. Ein/Ausgabe mit eigenen Operatoren.

    Für die, die es interessieren sollte, der exakte Wortlaut (Englisch):

    Redo [...], storing several (name,age) pairs in a class. Doing the reading and writing using your own >> and << operators.

    eigentlich hätte ich an sowas gedacht:

    struct NameAgePair {
        string name;
        int age;
        NameAgePair(const string& n, int a)
            : name{n}, age{a} { }
    };
    // ... operator<< ... operator>>
    int main()
    {
        vector<NameAgePair> pairs;
        // ...
    }
    

    Aber ich hab es in der Aufgabe so verstanden:

    class Persons {
    // ...
    private:
        vector<pair<string, int>> name_age_pairs;
    };
    

    Und nun zu meiner Frage: Wenn ich hier Ein- bzw. Ausgabe Operatoren definieren möchte, brauch ich ja Zugriff auf die `name_age_pairs`.
    Den hab ich aber so erstmal nicht, da ja private. Soll ich also nun das ganze einfach public machen, dann siehts ca. so aus:

    istream& operator>>(istream& is, Persons& p)
    {
        // Name und Alter einlesen
        p.name_age_pairs.push_back(make_pair(name, age));
        return is;
    }
    
    ostream& operator<<(ostream& os, const Persons& p)
    {
        for (const auto& i : p.name_age_pairs) {
            os << "Name: " << i.first << '\n'
               << "Alter: " << i.second << '\n';
        }
        return os;
    }
    

    Oder soll ich es private lassen, und eine `add` bzw `print` Funktion hinzufügen, die dann dementsprechend aufgerufen werden:

    // ...
    public:
        void add(const pair<string, int>& p)
        {
            name_age_pairs.push_back(p);
        }
        void print(ostream& os)
        {
            for (const auto& i : name_age_pairs) {
                os << "Name: " << i.first << '\n'
                   << "Age: " << i.second << '\n';
            }
        }
    // ...
    istream& operator>>(istream& is, Persons& p)
    {
        // Name und Alter einlesen
        p.add(make_pair(name, age));
        return is;
    }
    
    ostream& operator<<(ostream& os, Persons& p)
    {
        p.print(os);
        return os;
    }
    

    Das mag dem Einen oder Anderen jetzt als blöde oder triviale Frage erscheinen, aber es interessiert mich wirklich, insbesondere bei so einer `print` Funktion fühle ich mir vom Bauch her etwas komisch.
    Wär also nett, wenn mir jemand erklären könnte auf welche Art (oder vielleicht eine ganz andere) man das besser lösen sollte.
    Das lässt sich dann bestimmt auch allgemein recht gut anwenden.


  • Mod

    Entweder die print-Funktion oder eine friend-Funktion.





  • Du kannst die Operatoren als friend der Klasse deklarieren. Dann können sie auf private member zugreifen.

    Die Operatoren sind zwar keine Member aber haben quasi den selben Status. Sie sind immanente Bestandteile der Klasse.

    class Persons
    {
      std::istream& operator>>(std::istream& is, Persons& p);
      std::ostream& operator<<(std::ostream& os, Persons& p);
    ...
    };
    

    Ich empfehle übrigens immer den Präfix std:: zu verwenden. Im Header ist er sowieso notwendig da ein using namespace std quasi verboten ist. Konsequenterweise verwende ich ihn dann auch in der cpp.



  • @Caligulaminus 😃

    Also, wenn ichs richtig verstanden habe, dann definiere ich die ganz normal,
    deklariere sie in meiner Klasse aber noch zusätzlich als friend, so erhalten sie Zugriff auf die private member, ca. so:

    class Foo {
    public:
        friend ostream& operator<<(ostream& os, const Foo& f);
        friend istream& operator>>(istream& is, Foo& f);
    // ...
    };
    ostream& operator<< // ...
    istream& operator>> //...
    

    Funktioniert soweit, vielen Dank.


Log in to reply