Frage bzgl getter-Methode



  • 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.



  • Außerdem (bzw. wie man an der STL sieht) ist es eines der "schönsten" Features von C++.
    Damit verschwindet die Grenze zwischen "Objekt und Funktion" komplett..... 😃

    Gruß,

    Simon2.



  • Der operator() kommt vor allem zum Tragen, wenn man in C++ funktionale Programmierung anwenden möchte. Klassen oder Structs, die durch den operator() wie Funktionen benutzt werden, werden Funktoren genannt. Die STL unterstützt über den Header <functional> z. Bsp. Funktoren für die Grundrechenarten und bietet z. Bsp. im Header <numeric> Funktionen an, wo die Funktoren als Parameter verwendet werden können. Hier ein kleines Beispiel:

    #include <iostream>
    #include <vector>
    #include <functional>
    #include <numeric>
    using namespace std;
    
    template<template<typename> class TContainer, template<typename> class TOperation, typename T>
    struct Akkumulierer
    {
        Akkumulierer(T start) : m_start(start) {}
        T operator()(const TContainer<T> &values)
        {
            return accumulate(values.begin(), values.end(), m_start, TOperation<T>());
        }
    private:
        T m_start;
    };
    
    int main()
    {
        vector<int> test;
        test.push_back(3);
        test.push_back(5);
        test.push_back(2);
    
        Akkumulierer<vector, plus, int> summe(0);
        Akkumulierer<vector, multiplies, int> produkt(1);
    
        cout << summe(test) << "\n";
        cout << produkt(test) << "\n";
    }
    

    Funktoren können von C++ Compilern übrigens auch prima ge-inlined werden. Man erhält noch viel zusätzliche Funktionalität, indem man die Boost C++ Libraries verwendet. Dort gibt es unter anderem boost::function und boost::lambda.


Anmelden zum Antworten