Private Methoden



  • Es ist mir klar wie man private Methoden nutzt und erstellt, jedoch versteh irgendwie nicht wieso man sie in der Klasse deklariren muss.

    Eine private Methode wird ja nur intern genutz, ist also Teil der Implementierung der Klasse also geht es eigentlich nur die Übersetzungeinheit, in der die Klasse implementiert ist, etwas an ob es sie den gibt. Anders als bei Datamembern, beiflusst sie ja auch nicht die Größe der Klasse und ist somit für andere Übersetzungseinheiten überflüssig.

    Es gibt zwar ein paar Fälle wo man sie im Header declariren muss, wenn sie zum Beispiel virtual ist oder wenn sie von einer inline Funktion aufgerufen wird, aber generel ist sie im Header nutzlos.

    Wenn ich ein C interface in C oder C++ code, dann declariere ich die Interfacefunktionen in einem Header und implementiere sie dann in einer Übersetzungseinheit, wenn ich Hilfsfunktionen brauche dann kommen die entweder in ein namespace{} Block oder werden static gemacht und somit erfahren andere Einheiten nicht mal, dass es sie gib. Was sie ja nicht sollen da das die Kapselung brechen würde.

    Wenn man nun eine C++ Klasse codet dann übernehmen ja private Methoden die Aufgabe dieser Hilfsfunktionen, müssen aber im Header declariert werden. Wieso? wozu ist das gut?

    Kapselung könnte man damit auch nicht brechen. Wenn man nun in einer fremden Überetzungs eine private Methode declarieren würde dann könnte man die ja immer noch nicht aufrufen da man dafür eine public Methode braucht auf welche man aber kein Zugriff hat.

    Kann jemand mir bitte erklären wozu private Methoden in den Header müssen? oder ist das einfach etwas woran bei der Standardisierung nicht gedacht wurde? oder geht es und ich weis nur nicht wie? (für eine klare Antwort auf die letzte Frage wäre ich sehr dankbar.)



  • Hallo,

    du musst private Memberfunktionen genauso deklarieren, wie jede andere Funktion
    auch. Wie soll der Compiler sonst wissen, welche Funktion zur Klasse gehoert und
    welche nicht? Sie sind Teil der Klasse, daher gehoeren sie auch in die
    Klassendeklaration hinein.

    mfg
    v R



  • Irgendwer schrieb:

    Wenn man nun eine C++ Klasse codet dann übernehmen ja private Methoden die Aufgabe dieser Hilfsfunktionen, müssen aber im Header declariert werden. Wieso? wozu ist das gut?

    vielleicht wegen der einheitlichen syntax, damit es der compiler nicht so schwer hat, die methoden einer klasse zuzuordnen?



  • Es gibt ja technisch nicht *die* Datei, in der eine Klasse implementiert wird. Manuelle Abhilfe schafft das pimpl-Idiom (danach sollte man gut googlen können).



  • Es ist mir klar wie man private Methoden nutzt und erstellt, jedoch versteh irgendwie nicht wieso man sie in der Klasse deklariren muss.

    Finde ich auch doof, ergibt sich aber aus dem Übersetzungsmodell von C++.

    Eine private Methode wird ja nur intern genutz, ist also Teil der Implementierung der Klasse also geht es eigentlich nur die Übersetzungeinheit, in der die Klasse implementiert ist, etwas an ob es sie den gibt.

    Fast. Friends der Klasse dürfen das private-Interface einer Klasse ebenfalls benutzen. Damit sie dies aber möglich ist, müssen sie die Deklaration des Interfaces sehen (-> ergibt sich wiederum aus dem Übersetzungsmodell), also muss das private-Interface Teil der Klassendefinition sein.

    Wenn ich ein C interface in C oder C++ code, dann declariere ich die Interfacefunktionen in einem Header und implementiere sie dann in einer Übersetzungseinheit, wenn ich Hilfsfunktionen brauche dann kommen die entweder in ein namespace{} Block oder werden static gemacht und somit erfahren andere Einheiten nicht mal, dass es sie gib. Was sie ja nicht sollen da das die Kapselung brechen würde.

    Gut so. Etwas ähnliches solltest du mit privaten-Methoden machen.
    Falls die Methode nicht virtuell sein muss und nicht auf zuviele Daten der Klasse zugreifen muss, dann solltest du die private-Methode durch eine freie Funktion in der cpp-Datei der Klasse ersetzen. Diese gehört natürlich in einen unbenannten Namensraum bzw. sollte statisch sein.

    Wenn man nun eine C++ Klasse codet dann übernehmen ja private Methoden die Aufgabe dieser Hilfsfunktionen, müssen aber im Header declariert werden. Wieso? wozu ist das gut?

    Friends und Virtualität.



  • vielleicht wegen der einheitlichen syntax, damit es der compiler nicht so schwer hat, die methoden einer klasse zuzuordnen?

    Also wenn ich

    class A{
    
    };
    void A::foo(){
    
    }
    

    schreibe dann weis der Compiler ganz genau, dass ich will, dass foo Member von A ist. (siehe Fehlermeldung eines üblichen Compilers.)

    Es gibt ja technisch nicht *die* Datei, in der eine Klasse implementiert wird.

    Wo ist das Problem?

    Header:

    class A{
    public: 
      void func();
    };
    

    File1:

    void A::foo(){
      //...
    }
    

    File2:

    void A::foo();
    void A::func(){
      foo();
    }
    

    Ich sehe weder teschnische noch syntaxtische Probleme. Eine Hilfsfunktion muss ja nicht statiisch sein.

    Manuelle Abhilfe schafft das pimpl-Idiom (danach sollte man gut googlen können).

    Danke für den Tipp. Es interessiert mich aber wieso man das oder etwas ähnliches nicht erlaubt hat.

    Wie soll der Compiler sonst wissen, welche Funktion zur Klasse gehoert und
    welche nicht? Sie sind Teil der Klasse, daher gehoeren sie auch in die
    Klassendeklaration hinein.

    Ich weis nicht irgendwie hab ich das Gefühl, dass bei Templates viel komplizierteres von einem Compiler gefordert wird als hier (syntaktisch ist es ja kein Problem).



  • Wenn man nun eine C++ Klasse codet dann übernehmen ja private Methoden die Aufgabe dieser Hilfsfunktionen, müssen aber im Header declariert werden. Wieso? wozu ist das gut?

    Friends und Virtualität.

    Ich war ja auch nicht dafür, dass man private Methoden ausserhalb der Klasse declarieren muss sonder dafür, dass man es kann. Oben hab ich ja schon gesagt, dass wenn man eine private Methoden virtual (wie du jetzt), dass sie dann in die Klassendeclaration gehört. Ich hab auch noch den Fall von inline Funktion welche auf private Methoden zurückgreifen angeführt.



  • @operator void
    Ich hab mir jetzt mal angesehn was man unter "PimplIdiom" versteht und das ist nichts weiter als ein C interface mit ein C++ inline Wrapper im Header. Ist in vielen Fällen nützlich nur verliert man dadurch den OO Teil von C++.



  • Irgendwer schrieb:

    @operator void
    Ich hab mir jetzt mal angesehn was man unter "PimplIdiom" versteht und das ist nichts weiter als ein C interface mit ein C++ inline Wrapper im Header. Ist in vielen Fällen nützlich nur verliert man dadurch den OO Teil von C++.

    Ne. Da hast du dir wohl das falsche Idiom angeschaut. Pimpl aka Letter/Envelope aka cheshire cat aka Bridge geht so:

    class Foo
    {
    public:
         void func();
         void gunc();
    private:
         class Impl;
         Impl* impl_;
    };
    
    // Foo.cpp
    class Foo::Impl
    {
    public:
        // public interface von !Foo!
        void func();
        void gunc();
    private:
       // Daten von !Foo!
    };
    
    Foo::Foo()
        : impl_(new Impl())
    {}
    
    void Foo::func()
    {
        impl_->func();
    }
    ...
    

    Wo bitte ist da ein C-Interface? Und wo verliert man da irgendwas von OO?

    PS: Ignorierst du meinen friend-Hinweis völlig?



  • nicht aka Handle Body Idiom?



  • ????????? schrieb:

    nicht aka Handle Body Idiom?

    Ich hatte bereits das Gefühl, dass ich einen gängigen Namen vergessen habe 🙂
    Handle/Body ist natürlich ebenfalls ein gängier Name für diese "Compilation Firewall".

    PS: Die Trolltech-Leute nennen das Ganze das "D-Pointer"-Idiom.



  • Ich weis nicht irgendwie hab ich das Gefühl, dass bei Templates viel komplizierteres von einem Compiler gefordert wird als hier (syntaktisch ist es ja kein Problem).

    Hmmm...da koenntest du durchaus recht haben ;). Weiss ja nicht, wie
    kompliziert die Compilerbauer sich die ganzen Sachen machen 🙂

    mfg
    v R



  • @Hume
    da hatte ich wohl etwas ein wenig falsch verstanden.

    Trotzdem sehe ich nicht wo dieses Pimpl (nach deinem Beispiel code) einem C Interface + C++ Wrapper überlegen ist. Ich find den Syntax schwieriger (wenn auch leicht kürzer) dafür hat man dann eine zusätzlich Indirektion (this->impl_->member oder handle->member) und man alle Nachteile die man mit der uneiheitlichen C++ Namesdecorationen hat (die einem hier ja aber nicht wirklich Vorteile bringt).



  • @Irgendwer
    Worauf willst du jetzt hinaus? Das Pimpl-Idiom ermöglicht es dir private Implementationsdetails wirklich zu verstecken. Sie sind nicht nur gekapselt sondern auch unsichtbar für andere Klassen. In C++ muss man zwischen "Encapsulation" und "Insulation" (Implementationsdetails können geändert werden ohne das Clients neu kompiliert werden müssen) unterscheiden. Kapselung ("encapsulation") kannst du über die Access-Specifier erreichen. "Insulation" hingegen nicht. Pimpl ist eine "Insulation"-Technik, die auf *konkrete* Klassen angewendet werden kann. Die konkrete Klasse bleibt sichtbar, kann also direkt wiederverwendet werden.

    Eine andere "Insulation-Technik" ist z.B. die Kombination einer Protokoll-Klasse mit Erzeugungsfunktion + ein oder mehrere versteckte Implementationsklassen.
    Hier arbeitet der Client nie mit einer konkreten Klasse direkt sondern immer mit einer Referenz auf die Protokoll-Klasse.
    Auch diese Technik bezieht sich auf eine Klasse. Konkrete Klassen können aber nicht direkt wiederverwendet werden, da sie nicht sichtbar sind.
    Die Protokollklasse kann aber ganz normal erweitert werden (z.B. durch Vererbung)

    Ein C-Interface ist zwar letztlich auch eine "Insulation-Technik", verfolgt aber ganz andere Ziele. Normalerweise baut man ein solches Interface nicht klassenweise sondern für ein ganzes (Teil-)System.
    Implementationsklassen sind für Clients des Interfaces nicht sichtbar, können also nicht wiederverwendet werden. Ein solches Interface kann außerdem nicht funktional erweitert werden. Außerdem verlierst du natürlich auch die Kapselung von Daten und Funktionen.

    Mir ist nicht klar, wie du von deiner ursprünglichen Frage auf einmal auf die Probleme der C++ Namensdekoration kommst. Wenn du die Funktionalität einer C++ Klasse in anderen Sprachen wiederverwenden willst (z.B. in C), dann ist ein C-Interface eine gute Sache und Pimpl kann dir da nicht helfen. Nur ist das ja auch eine völlig andere Fragestellung.


Anmelden zum Antworten