C++ Schreib-still



  • 😮 sry, so eine Diskussion war nie meine Absicht...

    Dravere schrieb:

    @Arme, welche von Shade Of Mine in Stücke gehackt werden,
    Shade Of Mine wollte doch nur wissen, wie die Pimpl Klasse denn nun aufgebaut ist. Was wohl ziemlich schnell zum Schluss führen wird, dass sie genau gleich wie die normalen Klassen aufgebaut sind. Deswegen empfinde ich die Bemerkung von franz ziemlich überflüssig, denn irgendwo hat er seine Funktionen und co auch nach einem Schema organisiert. Oder hat er ein riesiges Durcheinander in der Pimpl Klasse, nur weil es eine Pimpl Klasse ist? Das würde ich als ziemlich dumm empfinden 🙂

    Also, prinzipiell schauen die private und die interface-header ähnlich aus. Mit dem einen unterschied dass die private eigentlich alles public haben (Zugriff hat ja eh nur die Q-Klasse).

    Und wenn der Kommentar überflüssig war, war es der auch auf den ich überhaupt geantwortet hab ("Private oben, da public-interface eh in der Doku steht"). Außerdem ist PIMPL selber in hohem Maße Übersicht fördernd, da einem die ganzen Member nicht ständig in der Quere sind (rein optisch), deshalb war der Kommentar auch nicht sooo überflüssig.



  • franz schrieb:

    Außerdem ist PIMPL selber in hohem Maße Übersicht fördernd, da einem die ganzen Member nicht ständig in der Quere sind (rein optisch), deshalb war der Kommentar auch nicht sooo überflüssig.

    Verstehe ich nicht. Warum kommen einem in der Impl Klasse die Member rein optisch nicht in die Quere?



  • Shade Of Mine schrieb:

    FreakY<3Cpp schrieb:

    void setData(T); ///nur den Typ und nicht den Namen der Variable festlegen
    

    Warum?

    Klar geht es, aber ich hab bisher noch nie in der Klasse den Variablennamen festgelegt.



  • Shade Of Mine schrieb:

    franz schrieb:

    Außerdem ist PIMPL selber in hohem Maße Übersicht fördernd, da einem die ganzen Member nicht ständig in der Quere sind (rein optisch), deshalb war der Kommentar auch nicht sooo überflüssig.

    Verstehe ich nicht. Warum kommen einem in der Impl Klasse die Member rein optisch nicht in die Quere?

    😕 Weil ein

    class Klasse {
    private:
       KlassePrivate* d;
    

    um einiges übersichtlicher ist als ein

    class Klasse {
    private:
       int m_length;
       int m_width;
       std::list<Pupil*> m_pupils;
       // und weitere Member
    

    Wenn man dann das private noch oben stehen hat kriegt man beim Blick in den Header echt nen Krampf. (Ganz zu schweigen von weiteren privaten Methoden samt kurzen Kommentaren).

    Im übrigen sollte es klar gewesen sein, dass ich nicht die Member der private-Klasse gemeint hab, sondern die der Interface-Klasse...



  • FreakY<3Cpp schrieb:

    Klar geht es, aber ich hab bisher noch nie in der Klasse den Variablennamen festgelegt.

    Mich würde das Warum interessieren...

    franz_ schrieb:

    😕 Weil ein

    class Klasse {
    private:
       KlassePrivate* d;
    

    um einiges übersichtlicher ist als ein

    class Klasse {
    private:
       int m_length;
       int m_width;
       std::list<Pupil*> m_pupils;
       // und weitere Member
    

    Wenn man dann das private noch oben stehen hat kriegt man beim Blick in den Header echt nen Krampf. (Ganz zu schweigen von weiteren privaten Methoden samt kurzen Kommentaren).

    Und wie sind dann KlassePrivate aus?
    Du brauchst int m_length und int m_width und m_pupils doch eh als Variablen. Klasse ist natürlich nur ein dummer proxy, aber mich interessiert das Layout in KlassePrivate. Dort hast du nämlich die ganzen privaten Funktionen und Member. Und das ist das interessante wie du sie dort angelegt hast.

    PS:
    deshalb fördert pimpl übrigens kein bisschen die Übersicht, weil du alles nur verschiebst. pimpl reduziert die abhängigkeiten - mehr aber auch nicht.



  • Ich glaube ich verstehe jetzt worauf Franz hinaus will und er würde in Java seine Schittstelle als interface schreiben und dieses dann implementieren, so trennt er effektiv die Implementierung von der Dokumentation der Schnittstelle.
    Könnte man in C++ auch so machen, allerdings hat man bei Pimpl auch gleich die Abhängigkeiten die die Implementierungsdetails mit sich bringen weg.



  • Tippgeber schrieb:

    Ich glaube ich verstehe jetzt worauf Franz hinaus will und er würde in Java seine Schittstelle als interface schreiben und dieses dann implementieren, so trennt er effektiv die Implementierung von der Dokumentation der Schnittstelle.
    Könnte man in C++ auch so machen, allerdings hat man bei Pimpl auch gleich die Abhängigkeiten die die Implementierungsdetails mit sich bringen weg.

    Natuerlich macht er das und pimpl macht ja auch Sinn. Aber darum geht es hier nicht. Es geht nicht um Bridge, Visitor, Pimpl, raii, etc. Sie alle machen Sinn.

    Aber hier geht es um den Coding Stil - um das Layout des Codes. Nicht das Design.

    Ist das so schwer zu verstehen?

    Deshalb nochmal:

    Coding Stil hat mit einrueckungen, namensgebung, reihenfolge der deklarationen, etc. zu tun und nichts mit bevorzugten design pattern. Deshalb:
    ich will wissen in welcher Reihenfolge die Elemente in der KlassePrivate vorkommen.

    Dort muessen Member Variablen und private bzw public Funktionen vorkommen. Die Reihenfolge dieser wuesste ich gerne - generell waere da ein Code Beispiel wie eben vom OP sehr nett anzusehen.

    Und nein, ich will nicht ueber Doc/View oder Adapter diskutieren, sondern einfach nur dummen sinnlosen Code sehen oder eine beschreibung wie er aussieht.



  • Shade Of Mine schrieb:

    Coding Stil hat mit einrueckungen, namensgebung, reihenfolge der deklarationen, etc. zu tun und nichts mit bevorzugten design pattern. Deshalb:
    ich will wissen in welcher Reihenfolge die Elemente in der KlassePrivate vorkommen.

    Dort muessen Member Variablen und private bzw public Funktionen vorkommen. Die Reihenfolge dieser wuesste ich gerne - generell waere da ein Code Beispiel wie eben vom OP sehr nett anzusehen.

    Und nein, ich will nicht ueber Doc/View oder Adapter diskutieren, sondern einfach nur dummen sinnlosen Code sehen oder eine beschreibung wie er aussieht.

    Um mein Beispiel aufzugreifen würde KlassePrivate etwa so ausschauen:

    class KlassePrivate {
    publilc:
       int length;
       int width;
       std::list<Pupil*> pupils;
       // und weitere Member
    

    Wenn ich auch Funktionen in KlassePrivate hab stehen die mit Leerzeilen getrennt VOR den Membervariablen.

    Es sollte klar sein, dass ein Blick in den Source nicht unbedingt den Wunsch bedeuten muss, zu sehen was "hinter der public-Schnittstelle" passiert (so wie du das ja auf Seite 2 andeutest). Denn die Member allein sagen ja noch herzlich wenig über (z.B.) Nebeneffekte von Funktionen aus. So was MUSS dokumentiert sein. Es kommt durchaus vor, dass Bibliotheken Closed Source sind, da kann man sich bei schlechter Dokumentation (oder überhaupt aus Interesse) mal die public Schnittstelle anschauen.
    Und allein hierauf war mein Kommentar bezogen, dass eigentlich die private Member auf den ersten Blick nicht interessieren. Und bei PIMPL steht halt dann einfach weniger im Header.
    Wenn der Source zur Verfügung steht, kann man sich doch auch sofort den private-Header holen und dann die Details rauspicken.

    Dass das allein kein Argument für dieses Idiom ist ist mir klar. Mir ist halt einfach dieser Punkt während der Diskussion hier aufgefallen.
    OK, ist vllt. kein gutes Beispiel, aber Qt wendet PIMPL ja an. Man stelle sich einfach mal vor, wie der Header von z.B. QWidget anschwillt, wenn da auch noch qwidget_p.h drin stehen würde (schlechtes Bsp. deshalb, weil die Doku einfach gigantisch ist...).

    Dass das aber nix mit Stil zu tun hat ist mir auch klar. Ich wollte hier auch nie eine Diskussion in diesen Ausmaßen anstoßen. Ich hab doch bloß auf diesen Beitrag geantwortet:

    Shade Of Mine schrieb:

    Aquae schrieb:

    Erst die public-Sachen, dann private... Den Benutzer kann ja nur das public interessieren

    Interessant, ich mache immer privat zuerst weil den Leser des Source Codes kann ja nur die interna interessieren - das public interface steht ja in der doku 😉

    Und wenn das in der Form ein Problem war tuts mir leid.



  • Kommentare wie "//----------> Getter! <----------//" sind für mich
    a) "noise"
    b) "undocumentation" (wassndas?)
    Finde ich garnicht gut.

    Wenn eine "optische Trennung" erwünscht ist, dann mach ich einfach ne Zeile

    /////////////////////////////////////////////////////////////////////////
    

    und gut is.

    Wenn wir allerdings zwischen jeder Funktion so eine Zeile einziehen ... sind wir schnell wieder beim Thema "noise".



  • @Shade Of Mine:
    Ich schätze du willst eigentlich wissen wie franz das macht, aber ich schreib trotzdem einfach mal wie sowas bei mir aussieht:

    #pragma once
    
    #include "Common.h"                // anm: erst "meine" header
    #include "WasIchNochBrauch.h"
    
    #include <cryptopp/blah.h>         // anm: dann "andere" header (diverse libs)
    #include <boost/noncopyable.h>
    
    #include <windows.h>               // anm: dann "standard" header
    #include <algorithm>
    
    namespace Blubb
    {
    
    ///////////////////////////////////////////////////////////////////////////
    
    class Foo:
        public XYZ,
        private boost::noncopyable
    {
        friend Bar;
    public:
        //! doku
        Foo();
    
        //! doku
        Foo(P1 p1, P2 p2);
    
        ~Foo(); // anm: bekommt sicher keine doku wenn's hier nicht was ganz seltsames zu beachten gibt
    
        size_t GetWidth() const;  //!< doku
        size_t GetHeight() const; //!< doku
    
    private:
        void Fun() const;
        void Joy();
    
        static void JoyJoyHappyHappyJoyJoy();
    
        class InnerClass
        {
            // ...
        };
    
        size_t m_width;   //!< doku
        size_t m_height;  //!< doku
        boost::shared_ptr<InnerClass> m_inner;
    };
    
    } // namespace Blubb
    


  • FreakY<3Cpp schrieb:

    Shade Of Mine schrieb:

    FreakY<3Cpp schrieb:

    void setData(T); ///nur den Typ und nicht den Namen der Variable festlegen
    

    Warum?

    Klar geht es, aber ich hab bisher noch nie in der Klasse den Variablennamen festgelegt.

    Das ist doch der Blanke Horror (tm)!

    Wenn ich in ein Header-File reingucke, dann will ich wissen was es für Funktionen gibt, was die machen, und welcher Parameter welcher ist.
    Wenn da keine Namen dabeistehen... toll. Ausserdem können die meisten IDEs Header-Files parsen und hübsche Hilfsfenster einblenden.
    Hilft mir aber wenig wenn in dem Hilfsfenster dann keine Parameter-Namen stehen.

    Und vonwegen festlegen: du legst garnix fest, du kannst bei der Implementierung einen ganz anderen Namen verwenden:

    //header:
    void Foo(int dasWasAusgedrucktWerdenSoll);
    
    //impl:
    void Foo(int v)
    {
        printf("%d\n", v);
    }
    


  • Bei mir kommt public immer zu erst.

    irgendwas.hpp
    
    class Manager
    {
    
        public:
    
      	// Ctor
    	// *@param none
        Manager();
    
    	// Dtor
    	// *@param none
        ~Manager();
    
    	// Call to initialize Manager
    	//	*@param name player name
    	//	*@return reference to this
        Manager& Init( const std::string & name);
    
        protected:
        // ....
    
        private:
        // ....
    };
    


  • Noch vergessen zu erwähnen, dass mein Schreibstil natürlich am Schönsten ist.



  • hustbaer schrieb:

    ...

    ...
    #include <cryptopp/blah.h>         // anm: dann "andere" header (diverse libs)
    ...
    #include <windows.h>               // anm: dann "standard" header
    #include <algorithm>
    

    Ich frage mich was an der windows.h Standard ist, wenn man im gleichen Zug die boost-Bibliotheken als "andere Header" auffasst... Was ist dann bitte schön Standard und was "Anderes" [Das Standard in diesem Fall nicht mit der Standardbibliothek zu tun hat, habe ich schon verstanden, aber wo ist die Grenzziehung?]... 😉

    cu André



  • asc schrieb:

    [Das Standard in diesem Fall nicht mit der Standardbibliothek zu tun hat, habe ich schon verstanden, aber wo ist die Grenzziehung?]... 😉

    windows.h hat jeder windows rechner. sie ist standardmäßig vorhanden.

    für boost muss ich extra etwas installieren.

    in meinen augen eine sinnvolle trennung



  • Ohje, da hab ich ja eine Diskussion angezettelt mit public und private - Reihenfolge 😃

    @Shade of Mine: Ich hoffe, ich habe dich richtig verstanden, dass ich mich unglücklich ausgedrückt habe? Natürlich interessieren einen manchmal auch die privaten Sachen (egal ob pimpl, oder Daten / Methoden).

    blah123 schrieb:

    irgendwas.hpp
    
    class Manager
    {
    
        public:
    
      	// Ctor
    	// *@param none
        Manager();
    
    	// Dtor
    	// *@param none
        ~Manager();
    
    	// Call to initialize Manager
    	//	*@param name player name
    	//	*@return reference to this
        Manager& Init( const std::string & name);
    
        protected:
        // ....
    
        private:
        // ....
    };
    

    @blah123:

    Rufst du die Init-Methode mehrmals auf? Ansonsten ist sowas IMHO ein Konstrukt aus C-Zeiten. In C++ werden dafür Konstruktoren benutzen...



  • @Aquae

    Nö. "Init" wird nur Einmal aufgerufen.

    #include <iostream>
    #include <string>
    
    class Manager
    {
    
        public:
    
      	// Ctor
    	// *@param none
        Manager();
    
    	// Dtor
    	// *@param none
        ~Manager();
    
    	// Call to initialize Manager
    	//	*@param path directory path
    	//	*@return reference to this
        Manager& Init( const std::string & name );
    };
    
    Manager::Manager()
    {
    	Init("yarr");
    }
    
    Manager::~Manager()
    {
    	// clean up
    }
    
    Manager & Manager::Init( const std::string & name)
    {
       printf("%s\n", name.c_str() );
    
       return *this;
    }
    
    int main()
    {
       Manager * _manage = new Manager();
       delete _manage;
       return 0;
    }
    

    Weiß nicht was daran aus "C-Zeiten" stammen soll, gut bis auf printf.. aber das is nur ne Angewöhnung da ich std::cout nicht mag.



  • sehe den Sinn in Init nicht.
    Erklaerst du mal warum du Init unbedingt brauchst?

    Und statt printf gibt es boost::format...



  • Shade Of Mine schrieb:

    sehe den Sinn in Init nicht.
    Erklaerst du mal warum du Init unbedingt brauchst?

    Und statt printf gibt es boost::format...

    "Init" war nur ein Modifiziertes Beispiel aus einem Programm. Boost hab ich auf der platte, brauchte es noch nicht so oft, bis auf boost::asio.

    Manager & Manager::Init( const std::string & path )
    {
    	WIN32_FIND_DATA	fileData;
    	HANDLE			fileHandle;
    	std::string		fileSearch;
    
    	fileSearch = path + "\\*.jpg";
    	fileHandle = INVALID_HANDLE_VALUE;
    	memset( &fileData, 0, sizeof( WIN32_FIND_DATA ));
    
    	fileHandle = FindFirstFileA( fileSearch.c_str(), &fileData );
    
    	do 
    	{
           if ( false == parseFileName( fileData.cFileName )) 
    	   {
    		   fileMap_.clear(); FindClose( fileHandle );
    	   }
    
    	} while ( TRUE == FindNextFileA( fileHandle, &fileData ));
    
    	FindClose(fileHandle); IsInit_ = true;
    
    	return *this;
    
    }
    

    Muss mir eig boost::filesystem angucken damit ich auf FindFirstFileA/FindNextFileA verzichten kann.



  • Sehe den Sinn davon immer noch nicht.

    Warum nicht in den CTor packen?

    Und warum kein einheitliches Namensschema und warum hat parseFileName Seiteneffekte und warum kein RAII um das doppelte FindClose zu verhindern?


Anmelden zum Antworten