Wann und Warum static?



  • Die Aussage von Meyers bezieht sich auf nicht-statische Methoden. Seine Begründung dafür ist dass die Kapselung davon profitiert, wenn weniger Code zugriff auf die Interna einer Klasse hat. Mit statischen Methoden hat das aber eher weniger zu tun.

    @RHBaum wtf sind "mehrfachüberladungen"? 😃

    @Skym0sh0 Anfangsfrage:
    Wenn etwas zur Klasse gehört aber nicht zu einem bestimmten Objekt, dann macht man es statisch. Eigentlich relativ offensichtlich. Oft braucht man das natürlich nicht, und wenn das so ist ist das eher ein gutes als ein schlechtes Zeichen. Ich habe allerdings z.B. öfter mal private statische Hilfsmethoden, weil man sowas bei Templates nicht in der Implementierungsdatei in einem anonymen namespace verstecken kann. Ein weiteres Beispiel für statische Methoden sind Singletons. (Welche übrigens generell als Antipattern gesehen werden, was ich auch verstehen kann, aber für Startup-Kram sind sie dennoch nützlich. z.B. für WSAStartup() bei Sockets.)



  • Ich denke auch nicht so ...

    zum beispiel hab ich oft den fall, das ich Objekte unterschiedlichen types mergen, oder convertieren muss ...

    ALso brauch ich sowas ca.

    int convert(const A * pFrom,B * pTo);

    da ich soweiso meist in nem Namspace bin, waers auch ok ....
    wenn die Funktion einfach zu implementieren waer.
    Isses aber meist nicht. DIe wuerde dann vielleicht mehrere tausend codezeilen gross, was doof und unleserlich ist. Oft brauch ich auch rekursion drinn.

    Also muss ich sie unterteilen.

    Ohne Klassencontext wuerd ich meinen Namespace zumüllen mit tonnen an funktionen ala convert_xyz ....

    nur lokal definieren in der cpp für die convert funktion ... brauchst aber richtige Reihenfolge, bzw forward deklarationen in der cpp.
    Waer machbar.

    Die funktionen alle in nen eigenen namespace packen ?
    find ich auch weniger schön ...

    Ich nutzt aber dann meist klassen ...

    sowas wie

    class XYZConverter
    {
    public:
        static int convert(const A * pFrom,B * pTo); 
    private:
        static int convert_xyz(....)
        ..... 
    };
    

    und nutzen tu ich dann

    iResult =XYZConverter::convert(a,b);

    Ich konnt mit nem globalen

    inline int convert(const A * pFrom,B * pTo){ return XYZConverter::convert(a,b);}
    

    die sache natuerlich global machen, aber warum ?
    So sehr stört mich die klassenkontext dann doch nicht.

    Der Vorteil der Klassenversion gegenueber lokalen funktionen ist, wenn man mit Visual Studio arbeitet, es lässt sich besser navigieren, da tut sich der VS leichter ^^

    "Probleme" haben beide Lösungen nicht, es ist reine Formsache, der compiler compiliert den Klassencontext eh weg ...
    Das Erstellen der standard Konstruktoren könnt ich auch noch verhindern wenns mich stören würde.
    Nen normaler compiler generiert die auch nicht, wenn man keine instanz erzeugt ...

    Ciao ...



  • D.h. statt eigene Namespaces oder als freie Funktionen baust du dir für naja größere Probleme eine Klasse mit nur statischen Methoden?! (Letztlich ja nur wegen der Namensgebung...)

    Mh, hör sich in meinen Ohren so etwas komisch an, weil dann hätteste direkt ne richtige Klasse bauen können, die genau für sowas zuständig ist.



  • @RHBaum wtf sind "mehrfachüberladungen"?

    Na wenn man die Überladung überlad .... 😃
    Sorry, Überladung hätte ausgereicht ^^

    weil dann hätteste direkt ne richtige Klasse bauen können

    Was verstehst du unter richtige Klasse ?
    Eine die man instanzieren muss ?

    Wenn A nach B konvertiert werden soll.
    Gehört das zu A oder zu B ? Schwer zu sagen oder ? Abhängig isses von beiden ...
    es an A oder B zu hängen macht oft keinen Sinn ...
    Aber dafuer noch ne Klasse C zu instanzieren, macht auch kein sinn ...

    Also iss ne globale oder pseudo globale Funktion dafuer schon eher sinnvoll.

    Ciao ...



  • Also Klassen als Namespace zu misbrauchen halte ich doch für eine etwas fragwürdige Praxis. 😉



  • Wenn das so weitergeht, muss der Thread bald ins Java-Forum.

    Pack die Implementationsroutinen in der ÜE in den namenslosen Namensraum, wo sie keiner sieht und sie keinen stören; dann kann der Compiler auch besser optimieren (weil er weiß, dass die anderswo nicht gebraucht werden). Forward-Deklarationen braucht das womöglich, aber die hast du im Moment auch (nur halt in der "Klasse").



  • RHBaum schrieb:

    weil dann hätteste direkt ne richtige Klasse bauen können

    Was verstehst du unter richtige Klasse ?
    Eine die man instanzieren muss ?

    Ja

    RHBaum schrieb:

    Wenn A nach B konvertiert werden soll.
    Gehört das zu A oder zu B ? Schwer zu sagen oder ? Abhängig isses von beiden ...
    es an A oder B zu hängen macht oft keinen Sinn ...
    Aber dafuer noch ne Klasse C zu instanzieren, macht auch kein sinn ...

    Naja, wenn du möchtest, dass eine Klasse A aus einer Klasse B erstellt werden kann (was anderes ist eine Konvertierung ja nicht), dann biete einen ensprechenden Konstruktor an. Und zack, da hast du deine Konvertierungsfunktion.



  • Was ist genau der Nachteil?

    Die Technik ist an sich nicht ungewöhnlich ...
    Templateprogrammierung, Wenn man mehrere Funktionen gleichzeitig mit nur einem Typ Switchen will / muss , Policy-Klassen ...

    Weil ich es hier ohne templates mache, ist es böse ?

    Ciao ...



  • Der Nachteil ist dass diese Funktionen nach außen sichtbar sind und den Header zu müllen. Und bei Templates hat man keine Wahl, deshalb ist das da akzeptiert.



  • Mir ist nicht ganz klar, was du mit "mehrere Funktionen gleichzeitig mit nur einem Typ Switchen will / muss" meinst. Was den anderen Kram angeht, so ist Templatemetafoo ein ganz anderer Hund; wenn du das Typsystem programmieren willst, kommst du um Typen nicht wirklich herum (und Namespace-Templates gibt's halt nicht, obwohl das vielleicht mal ne Idee wäre).

    Aber es geht auch gar nicht um böse oder nicht, sondern darum, ohne Not die Beschränkungen einer Klasse in Kauf zu nehmen. Du musst den gesamten Inhalt der Klasse samt privater Funktionen (also Implementationsdetails) im Header bekannt machen, was konzeptionell unschön ist und bei jeder Änderung der Interna dazu führt, dass sämtlicher Clientcode neu übersetzt werden muss. Du kannst die Klasse nicht auf mehrere Header aufspalten. Du kriegst schlechter optimierten Maschinencode. Du hast sogar mehr Schreibaufwand. All das ist stumpf nicht notwendig.



  • @seldon

    Mal abgesehen von:

    Du kriegst schlechter optimierten Maschinencode

    hasst du technisch natürlich recht.

    Aber Hallo, wir sind beim normalen implementieren.

    Wenn du konsequent weiter denkst, gilt das was Du darlegst natürlich auch fuer alle privaten nicht virtuellen methoden ohne friend access !
    Wer macht private virtuelle methoden ???

    private deklarationen will man ja eigentlich per definition nicht weitergeben. Am liebsten soll man sie gar niemand sehen ^^
    Bei variablen hat man anders keine chance (allokation) als das sie im header stehen muessen.
    Aber statische private member haetten da nix zu suchen. Die kannst du auch alle mit dem selben aufwand was mir vorschlägst, durch lokale funktionen eliminieren.
    Warum macht man es da denn nicht ? Weil der Header durch die lokalen variablen eh versaut ist ?

    Ich denk es ist einfach uebersichtlicher, und die IDE's kommen damit besser klar bei der darstellung ...
    Und genau deswegen mach ich sowas auch, es ist einfach uebersichtlicher und bequemer, man kann dank tools besser navigieren, als wenn du zig private funktionen in einer cpp hasst.

    Woellte ich 100% information hiding, wuerd ich auch anders vorgehen. Aber das sind Arbeits/Implementationsdinge, kein öffentliches Interface ....

    Ciao ...



  • RHBaum schrieb:

    Wer macht private virtuelle methoden ???

    Ist bloss ein sehr übliches C++Idiom
    http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Non-Virtual_Interface



  • Aber statische private member haetten da nix zu suchen. Die kannst du auch alle mit dem selben aufwand was mir vorschlägst, durch lokale funktionen eliminieren.

    Exakt. Warum braucht man eigentlich private statische Memberfunktionen? Also mal von template metafoo abgesehen?



  • otze schrieb:

    Exakt. Warum braucht man eigentlich private statische Memberfunktionen? Also mal von template metafoo abgesehen?

    malloc oder ähnliches für die freiliste, Klassenspezifische Objekt-IDs erzeugen für Verwendung im Konstruktor, Singletons.



  • das erste hab ich nicht verstanden, 2 habe ich ehrlich gesagt nie gebraucht und singleton ist bei mir in etwa bei goto angesiedelt.



  • malloc oder ähnliches für die freiliste, Klassenspezifische Objekt-IDs erzeugen für Verwendung im Konstruktor, Singletons.

    Und auch das könntest Du genau so mit globalen Methoden ersetzen.

    Am Ende isses ein Gestaltungsmittel ...

    und singleton ist bei mir in etwa bei goto angesiedelt.

    Manche sehen Singletons als total sexy an ...
    Manche sehen Singletons nur als aufwendiger formulierte Form einer globalen Variable (absolut unattraktiv) ...

    Wenn Du das Design 100% selbst in der Hand hasst, brauchst du dann globale Variablen ?

    Was ist nun gut, was ist nun schlecht ? Und wer bestimmt das ?

    Ciao ....



  • cooky451 schrieb:

    @Skym0sh0 Anfangsfrage:
    Wenn etwas zur Klasse gehört aber nicht zu einem bestimmten Objekt, dann macht man es statisch. Eigentlich relativ offensichtlich. Oft braucht man das natürlich nicht, und wenn das so ist ist das eher ein gutes als ein schlechtes Zeichen. Ich habe allerdings z.B. öfter mal private statische Hilfsmethoden, weil man sowas bei Templates nicht in der Implementierungsdatei in einem anonymen namespace verstecken kann. Ein weiteres Beispiel für statische Methoden sind Singletons. (Welche übrigens generell als Antipattern gesehen werden, was ich auch verstehen kann, aber für Startup-Kram sind sie dennoch nützlich. z.B. für WSAStartup() bei Sockets.)

    RHBaum schrieb:

    Manche sehen Singletons als total sexy an ...
    Manche sehen Singletons nur als aufwendiger formulierte Form einer globalen Variable (absolut unattraktiv) ...

    Und beide liegen falsch.

    RHBaum schrieb:

    Was ist nun gut, was ist nun schlecht ?

    Schlecht sind z.B. statische Memberfunktionen die nicht unmittelbar zur Klasse gehören und die man auch in eine .cpp Datei schieben könnte. Oder Singletons die globale Variablen modellieren. Oder Leerzeichen vor Satzzeichen.

    Und wer bestimmt das ?

    Ich. 😉



  • cooky451 schrieb:

    Und wer bestimmt das ?

    Ich. 😉

    Ich nicht?

    *okayface.png*


Anmelden zum Antworten