Wie einmal const und einmal normale Version einer Funktion in eine Implementierung packen?



  • Hi,

    wie löst ihr das immer wiederkehrende Problem der Codeduplizierung, wenn ihr einmal eine Version irgendwas & getFoo() und einmal const irgendwas & getFoo() const habt, welche eigentlich das gleiche tun, nur einmal eben Schreiben erlauben und einmal eben nicht?


  • Mod

    Ich schreibe beide Versionen aus. Diese Fall kommt zwar immer mal wieder gelegentlich vor, aber bei weitem nicht so häufig, als dass man sich tolle Techniken überlegen müsste um Codeduplizierung zu vermeiden. Getter sind üblicherweise Einzeiler die sich nie verändern und man kann die nicht-const Version in wenigen Sekunden kopieren und zu const umschreiben. Alles weitere lohnt nicht.



  • Mir geht es genauso wie SeppJ. Bisher wäre mir mit einem Versuch, Codeduplizierung zu vermeiden, meist nur noch viel mehr Code (reiner Overhead ohne wirkliche Logik) entstanden.

    Ansonsten kannst du eine private Methode anbieten, die zwar const -qualifiziert ist, aber ein Objekt oder eine Referenz/Zeiger auf Non-Const-Objekte zurückgibt. Manche Leute halten diese Situation auch für einen der wenigen berechtigten Anwendungen von const_cast . Ich selbst habe es noch nie wirklich benötigt.



  • Was spricht gegen

    const irgendwas & getFoo() 
    {
        return getFoo();
    }
    

    ?

    Wenn wenn das Call+Return stört kann man ja auch eine inline-Funktion aus getFoo() machen.



  • stefan-tiger schrieb:

    Was spricht gegen

    const irgendwas & getFoo() 
    {
        return getFoo();
    }
    

    Dass die Funktion nicht const -qualifiziert ist und somit nicht bei konstanten Objekten aufgerufen werden kann. Sobald sie aber const -qualifiziert wäre, könnte sie keine Nicht- const -Funktionen mehr aufrufen.



  • Manche Leute halten diese Situation auch für einen der wenigen berechtigten Anwendungen von const_cast. Ich selbst habe es noch nie wirklich benötigt.

    ich halts eher so: implementiere die const variante und verwende die dann in der non-const version mit 'nem const_cast. Gabs wohl auch ein Scott Meyers - item zu....
    Ich hab halt eine manchmal irrationalte Abneigung gegen copy - paste....

    Viele Gruesse,

    Tobias



  • Wirklich häufig taucht das Problem bei mir auch nicht auf, aber es sind halt immer solche Fälle in denen man zwei Codepfade hat die man Warten muss. Wenn nur ein Attribut zurückgeliefert wird ist es auch gar kein Problem, in meinem Fall wird allerdings ein Element aus einem Cache zurückgeliefert und im Falle eines Schreibzugriffs muss ich mir merken, dass die Daten jetzt modifiziert wurden und auf Festplatte zurückgeschrieben werden müssen. Aber ich hab es jetzt ganz einfach gelöst, statt eine Referenz auf das Element gibt es jetzt einfach ein irgendwas read(unsigned irgendwasId) const und ein void write(unsigned irgendwasId, const irgendwas &foo), alles andere wäre ja nur Kosmetik 🙂



  • Solche Funktionen sind im Normalfall maximal Zweizeiler, da lohnt es nicht sich irgendeinen Aufwand zu überlegen und mit unschönen const_casts zu hantieren... Kopieren reicht 🙂



  • Ein C++ Anfänger schrieb:

    Aber ich hab es jetzt ganz einfach gelöst, statt eine Referenz auf das Element gibt es jetzt einfach ein irgendwas read(unsigned irgendwasId) const und ein void write(unsigned irgendwasId, const irgendwas &foo), alles andere wäre ja nur Kosmetik 🙂

    Die Variante mit Value-Getter/-Setter und die Referenz-Getter Variante sind IMO ziemlich unterschiedlich.
    Mit Value-Getter/-Setter hast du ne gute Kapselung, dafür kann der User gewisse Dinge nicht machen (wie z.B. Member-Funktionen auf "irgendwas" aufrufen).
    Mit der Referenz-Getter ermöglichst du das (Aufruf von Member-Funktionen), dafür ist wie gesagt die Kapselung mehr oder weniger futsch.

    Ich würde das nicht anhand der Syntax entscheiden, sondern danach was du eigentlich haben bzw. erlauben willst.


Anmelden zum Antworten