Frage bzgl getter-Methode



  • Artchi schrieb:

    Normalerweise behandelt man ja einen string als logische Einheit und dann reicht es aus, ihn als Ganzes rauszugeben.

    Exakt! Und warum sollte das nicht auch bei einem vector der Fall sein?

    Logisch gesehen ist es beim vector genauso. Allerdings liegt semantisch gesehen der Fokus des Vector auf seinen einzelnen Elementen, während der Fokus des Strings auf der Zeichenkette als Gesamtheit liegt.

    Man kann nicht pauschal sagen, der vector muß 100% gekapselt werden. Man muß erstmal den Kontext und die fachlichen Anforderungen berücksichtigen. Manchmal leitet man ja sogar vector private ab, und nutzt ihn nicht als einfaches Member. Weil ich halt den vector in dem speziellen Fall einem ganz anderen Kontext sehe.

    Und genau diesen Kontext hebelst du aus, wenn der getter eine Referenz auf deine internen Daten zurückgibt. Da kannst du dir gleich die Schreibarbeit sparen und die Daten public setzen - der Effekt ist der selbe.



  • Badestrand schrieb:

    Simon2 schrieb:

    Hast Du zufällig meinen Beitrag gelesen ?

    Öhh ja... Willst du damit sagen ich hätte genau das gleiche geschrieben?

    Grüße

    Sagen wir mal so: Da Du "ihr" geschrieben hattest war ich mir nicht ganz sicher, ob ich mitgemeint war.
    ... und da habe ich jetzt nicht so ganz verstanden, wo Deine Kritik an meinem Ansatz liegt.

    Gruß,

    Simon2.



  • Artchi schrieb:

    Sorry, aber irgendwie finde ich die Diskussion sinnlos. Ein Beispiel:

    class A
    {
      private:
        string name;
      public:
        string& getname();
        void setname(string);
    }
    

    Wie würdet ihr das hier lösen? string ist immerhin auch ein Container. Muß ich name jetzt auch nochmal kapseln?...

    Gegenfrage: Wie würdest Du Deine Frage beantworten, wenn Du in der nächsten Version Deines Programms den Namen aus einer DB liest ? Oder intern doch lieber als vector<char> oder char[25] ablegen willst ?

    Alle Aufrufer gehen inzwischen davon aus, dass sie mit doSomething(a.getname()) den Zustand von a ändern .....

    Gruß,

    Simon2.



  • eine wirklich interessante diskussion, da dachte ich ich frage die totale newbie sache die sich als einfach zu beantworten und glasklar darstellt, und dann kommt sowas dabei raus ( im positiven sinne ) 😉

    worauf ich bei all den geposteten möglichkeiten nochmal hinweisen möchte, ist, dass es mir nicht darum ging, dass es jetzt unbedingt ein vector sein muss. mich würde das ganze schon eher datentyp-unabhängig interessieren.

    da mich einige posts ehrlich gesagt ein wenig durcheinander gebracht haben, vllt nochmal der aufruf wie das ganze denn nun aussehen sollte und umzusetzen ist.

    ein beispiel:

    Test.h:

    class Test {
     private:
        int value;
    };
    

    wie sähen jetzt die getter und setter auf int value sowohl in der Test.h als auch in der Test.cpp datei aus?

    sollte hier jemand eine möglichkeit posten, wäre ich über eine begründung, vor oder nachteile, dankbar 🙂 hilft sicherlich auch der diskussion

    ich hoffe meine erneute anfrage kommt nun nicht total nervend rüber, auch möchte ich die diskussion dadurch keinesfalls beenden 🙂

    danke @ alle beteiligten



  • Ui ui, also native Datentypen, da ist die Situation auch schon wieder anders. Das ist ja halt der Witz an der Sache!

    int getValue();
    void setValue(int i);
    

    Unterschied ist hier, das es keine Diskussion geben kann, weil man int bzw. native Typen nicht als Ref über- oder zurückgibt. 😉

    Wobei ich dann bei dieser Betrachtung schon wieder dem readonly-Gedanken bei get zustimmen muß. Denn implizit habe ich bei nativen Typen ohne Ref-Operator schon wieder nur eine readonly-Situation.

    Würde mal sagen, die Readonly-Fraktion bzgl. getter hat gewonnen. 🙂



  • Artchi schrieb:

    Wobei ich dann bei dieser Betrachtung schon wieder dem readonly-Gedanken bei get zustimmen muß. Denn implizit habe ich bei nativen Typen ohne Ref-Operator schon wieder nur eine readonly-Situation.

    Ja, aber hier besteht auch gar nicht die Notwendigkeit einer Unterscheidung zwischen Modifikation und Zuweisung d.h. das Problem ergibt sich gar nicht erst.

    Ich finde nicht, dass man pauschal alles über ein Messer scheren kann. Es mag sinnvoll sein, mit eigenen Klassen die POD-Funktionalität nachzustellen -- aber irgendwo sollte man eine Grenze ziehen.



  • Ein Member, das wenig Spiecher verbraucht, wird gewöhnlich durch den getter einfach rauskopiert:

    //.h
    class Test
    {
    public:
        int getValue() const;
    private:
        int value;
    };
    
    //.cpp
    inline int Test::getValue() const
    {
        return value;
    }
    

    Solch kleine Methoden definiert man aber auch gerne direkt in der Klasse (.h Datei) und macht sie damit implizit inline.



  • test-mensch schrieb:

    ich hoffe meine erneute anfrage kommt nun nicht total nervend rüber, auch möchte ich die diskussion dadurch keinesfalls beenden 🙂

    Ist immer noch dein Thread 😉

    [Noch in der Vorschau]Ok, die Setter/Getter-Frage wurde geklärt^^[/]

    @Simon2: Habe keine Kritik an deinem Ansatz, tut mir Leid wenn das so rüber gekommen ist! Mir kam es nur so vor als ob es nur noch darum ging, wie man am besten einen vector samt allen Members kapselt...



  • Artchi schrieb:

    Ui ui, also native Datentypen, da ist die Situation auch schon wieder anders. ...

    Wieso ? 😕

    Kapselung ist Kapselung....

    Gruß,

    Simon2.



  • Badestrand schrieb:

    ...
    @Simon2: Habe keine Kritik an deinem Ansatz...

    OK, dann sind wir uns einig und können uns auf :xmas1: freuen.

    (Die smilies sind einfach süüüüüß).

    Gruß,

    Simon2.



  • Simon2 schrieb:

    Artchi schrieb:

    Ui ui, also native Datentypen, da ist die Situation auch schon wieder anders. ...

    Wieso ? 😕

    Kapselung ist Kapselung....

    Ist mir auch klar! Ich bezog mich auf den technischen Aspekt! Du mußt meinen Beitrag als ein ganzes lesen, nicht nur die Einleitung einzeln betrachten.



  • test-mensch schrieb:

    eine wirklich interessante diskussion, da dachte ich ich frage die totale newbie sache die sich als einfach zu beantworten und glasklar darstellt, und dann kommt sowas dabei raus ( im positiven sinne )

    Vieles in der Programmierung hat auch was mit Konzepten und Design zu tun. Und da gibt es halt unterschiedliche Vorstellungen. Es ist nirgends ein ultimatives Gesetz festgeschrieben, wie ein Getter auszusehen hat. C++ ist nur ein Werkzeug, ein flexibles Werkzeug, das verschiedene Konzepte erlaubt.

    Wäre C++ unflexibel, würde es wahrscheinlich eine festgeschriebene Getter-Konstruktion geben. Aber das wäre halt auch unspannend. 😉



  • Artchi schrieb:

    ...Du mußt meinen Beitrag als ein ganzes lesen, nicht nur die Einleitung einzeln betrachten.

    Das habe ich schon gemacht; nichtsdestotrotz halte ich die Grundannahme für falsch, dass man hier prinzipiell unterscheiden müsse. Im Gegenteil bin ich der Meinung, dass solche Konzepte (wie die Kapselung) erst einmal typunabhängig sind.
    Es ist mE die Regel, dass man auch "komplexe Typen" sauber kapselt (z.B. nur als Kopie oder const-ref "raus-gettet") und bestenfalls eine Ausnahme, wenn man sie durchbricht (PODs und/oder notwendige Optimierungen).

    Das klingt in Deinem Posting anders...

    Gruß,

    Simon2.



  • schorsch code schrieb:

    //.cpp
    inline int Test::getValue() const
    {
        return value;
    }
    

    Sorry, das mit dem inline in der .cpp Datei der Klasse ist Quatsch, weil der Linker dann in der anderen .cpp Datei des Hauptprogramms den Einsprungpunkt für Test::getValue nicht findet.
    Also inline nur in der .h Datei, oder der .cpp Datei mit dem Haupteinsprungspunkt verwenden.



  • @Simon2! Nein, hast du anscheinend immer noch komplett gelesen. Denn was schreibe ich denn zum Ende meines Postings, nachdem ich meine ursprünglichen Gedanken verfasst habe? Eben! Ich bin zu der Einsicht gekommen, das alles gekapselt werden muß. Weil implizit durch native Typen ich diese Regel "readonly bei get" immer gehabt habe.



  • Wenn eine Methode "readonly" ist, sollte man das dem Compiler aber auch mittels des Schlüsselworts const mitteilen, um die Methode auch aufrufen zu können, wenn man const Referenzen oder Zeiger auf const hat. Infos dazu gibt es unter anderem als Beitrag auf HumeSikkins' Homepage.



  • Artchi schrieb:

    @Simon2! Nein, hast du anscheinend immer noch komplett gelesen. Denn was schreibe ich denn zum Ende meines Postings, nachdem ich meine ursprünglichen Gedanken verfasst habe? Eben! Ich bin zu der Einsicht gekommen, das alles gekapselt werden muß. Weil implizit durch native Typen ich diese Regel "readonly bei get" immer gehabt habe.

    😮 Also ich muß gestehen, dass ich Dein Posting nicht so verstanden habe ...

    Naja, nun aber ist es mir klar.

    Gruß,

    Simon2.



  • Ich finde nicht, man sollte bei nativen Typen IMMER ohne Referenzen arbeiten. Hier ein Beispiel, bei dem ich Referenzen auf native Typen ganz nett finde:

    #include <iostream>
    using namespace std;
    
    template<typename T, int rows, int cols>
    class matrix
    {
        T m_values[rows * cols];
    public:
        matrix()
        {
            for(int i = 0; i < rows*cols; ++i)
                m_values[i] = 0;
        }
    
        int colCount() const { return cols; }
        int rowCount() const { return rows; }
    
        T &operator()(int row, int col) { return m_values[row*cols + col]; }
    };
    
    int main()
    {
        matrix<float, 3, 4> m;
    
        m(0, 0) = 1;
        m(1, 1) = 1;
        m(2, 2) = 1;
    
        for(int i = 0; i < m.rowCount(); ++i)
        {
            for(int j = 0; j < m.colCount(); ++j)
                cout << m(i,j) << " ";
            cout << "\n";
        }
    }
    


  • 😮
    Den Operator () kenn ich gar nicht... Abgefahren 😋



  • Der ()-Operator ist immens wichtig für die Standardlib, ohne geht damit garnichts als StdLib-Anwender.


Anmelden zum Antworten