Seite 1 von 2

C/C++ Style-Guide

Verfasst: Do Mai 05, 2011 1:33 pm
von Xin
Ich möchte hier mit euch mal einen Style-Guide diskutieren.

Code: Alles auswählen

class Klassenname : public Basis1
                               , public Basis2
{
private:
    int   Member1;
public:
    int   Member2;

    int const Konstante1;

    Klassenname( int member1, int member2 )
    : Member1( member1 )
    , Member2( member2 )
    {
        DoSomething();
    }

private:
    void         DoSomething();
    unsigned int PrivateMethod( unsigned int a, unsigned int b );

protected:
    unsigned int ProtectedMethod( unsigned int a, unsigned int b );

public:
    unsigned int PublicMethod( unsigned int a, unsigned int b );
    unsigned int member1() { return Member1; }
    void              setMember1( int m1 ) { Member1 = m1; }
    unsigned int getMember2() { return Member2; }

};


unsigned int Klassenname::PrivateMethod( unsigned int a, unsigned int b )
{
  unsigned int result;

  result = a + b;

  return result;
}

static unsigned int staticFunction( unsigned int aSummand1, unsigned int aSummand2 )
{
  unsigned int result;

  result = aSummand1 + aSummand2;

  return result;
}

unsigned int GlobalVariable;
Wie würdet ihr die Klasse formatieren?
Sollte ein Getter auch getMember() heißten oder nur member()?
Inbesondere interessiert mich hier die Namen der Variablen. Groß- oder Kleinschreibung? javaNotation, CamelCase, CAPITALS, getMember(), GetMember(), get_Member() oder get_member()?
Sollen Membervariablen wie hier Member1 lieber mMember1 oder _Member1 oder member1_ heißen?
Sollen Funktions-Parameter Präfixe haben, wie das 'a' bei staticFunction()?

Was nutzt ihr - und vor allem - warum macht ihr es so?

Ich möchte hier einen logischen Style-Guide entwickeln - der auch mal vernünftig begründet werden kann.
Entsprechend werden die C-Quellen hier angepasst und ich werde mein komplettes Framework danach umbauen.
Aber dafür möchte ich halt einen durch und durch durchdachten und logischen Styleguide auf proggen.org beschreiben können.

Ggfs. einfach mal den Quelltext so formatieren, wie ihr ihn formatieren würdet - und beschreiben, warum ihr Änderungen gemacht habt.

Re: C/C++ Style-Guide

Verfasst: Do Mai 05, 2011 4:09 pm
von nufan
Bei mir würde das in etwas so aussehen:

Code: Alles auswählen

class Klassenname : public Basis1, public Basis2
{

  public:  
    Klassenname( int member1, int member2 );
    unsigned int publicMethod( unsigned int a, unsigned int b );
    unsigned int member1() const;
    void setMember1( int m1 );
    int m_member2;
    int const m_konstante1;

  protected:
    unsigned int protectedMethod( unsigned int a, unsigned int b );

  private:
    int m_member1;
    void doSomething();
    unsigned int privateMethod( unsigned int a, unsigned int b );
  
};


Klassenname::Klassenname( int member1, int member2 ) : m_member1( member1 ), 
                                                                                       m_member2( member2 )
{
  doSomething();
}


int Klassenname::member1() const
{
  return m_member1;
}


void Klassenname::setMember( int m1 )
{
  m_member1 = m1;
}


unsigned int Klassenname::protectedMethod( unsigned int a, unsigned int b )
{
  // ...
}


unsigned int Klassenname::privateMethod( unsigned int a, unsigned int b )
{
  // Leerzeilen hier normal nur bei längerem Code.
  unsigned int result;
  
  result = a + b;
  
  return result;
}

static unsigned int staticFunction( unsigned int aSummand1, unsigned int aSummand2 )
{
  // Gleiches wie oben.
  unsigned int result;

  result = aSummand1 + aSummand2;
  
  return result;
}

unsigned int globalVariable;
Methoden und Member ordne ich nach Zugriffsrechten.
Groß schreibe ich eigentlich nur Typen und public static Konstanten, die haben auch kein Präfix. Für nicht-public static Variablen und Konstanten verwende ich noch ein sm_-Präfix.
Ich halte mich auch nicht immer genau daran, meistens nach Gefühl ;)

Re: C/C++ Style-Guide

Verfasst: Do Mai 05, 2011 4:43 pm
von Xin
member2() oder getMember2() ?

Re: C/C++ Style-Guide

Verfasst: Do Mai 05, 2011 7:07 pm
von nufan
Xin hat geschrieben:member2() oder getMember2() ?
member2(). Außer bei bool-Werten, da würde das isSomething() oder hasSomething() heißen.

Re: C/C++ Style-Guide

Verfasst: Fr Mai 06, 2011 12:54 am
von Dirty Oerti
Schließe mich dani93 an.
Entspricht sehr genau auch meinem üblichen Codestil.
Einzig hätte ich evtl eine Einrücktiefe von 4 Leerzeichen.

Re: C/C++ Style-Guide

Verfasst: Fr Mai 06, 2011 9:30 am
von Xin
Begründungen?
Warum member() und setMember() statt getMember() und setMember()?


EDIT: Wie kommentiert ihr?

Re: C/C++ Style-Guide

Verfasst: Fr Mai 06, 2011 1:15 pm
von nufan
Xin hat geschrieben:Begründungen?
Warum member() und setMember() statt getMember() und setMember()?
Weil ich das get überflüssig finde.
Xin hat geschrieben:EDIT: Wie kommentiert ihr?
Im Header eine Beschreibung zur Klasse als Blockkommentar, über jeder Methode und jedem Member ein einzeiliger Kommentar. In der Quelldatei falls notwendig noch ein Blockkommentar über jeder Methode mit Parameter und Rückgabewert (für Doxygen). Innerhalb von Methoden normalerweise einzeilig über dem Code, an komplexeren Stellen ein Blockkommentar über dem Code.

Re: C/C++ Style-Guide

Verfasst: Fr Mai 06, 2011 1:57 pm
von Xin
dani93 hat geschrieben:
Xin hat geschrieben:Begründungen?
Warum member() und setMember() statt getMember() und setMember()?
Weil ich das get überflüssig finde.
Ist es denn logisch mal ein Präfix zu setzen (set, is, m_, sm_, aSummand) und es dann bei get überflüssig zu empfinden? Ein Parameter (aSummand) ist auch nur eine normale lokale Variable, warum ist das a als Prefix hier nicht überflüssig?
dani93 hat geschrieben:
Xin hat geschrieben:EDIT: Wie kommentiert ihr?
Im Header eine Beschreibung zur Klasse
Wie unterteilst Du Abschnitte innerhalb der Klasse im Headern und der .cpp-Datei?

Re: C/C++ Style-Guide

Verfasst: Fr Mai 06, 2011 2:13 pm
von nufan
Xin hat geschrieben:Ist es denn logisch mal ein Präfix zu setzen (set, is, m_, sm_, aSummand) und es dann bei get überflüssig zu empfinden?
Naja Geschmackssache, m_ und sm_ verwende ich zur Unterscheidung von lokalen Variablen. is und set weil es sich schöner liest.
Xin hat geschrieben:Ein Parameter (aSummand) ist auch nur eine normale lokale Variable, warum ist das a als Prefix hier nicht überflüssig?
Oh, ich hab gedacht das steht für einen Parameter mit mehreren Wörtern ^^ Dann würde ich summand1 und summand2 schreiben.
Xin hat geschrieben:Wie unterteilst Du Abschnitte innerhalb der Klasse im Headern und der .cpp-Datei?

Code: Alles auswählen

   
    // Header
    /*!
     * Ein ausführlicher Kommentar der die Klasse beschreibt.
     */
    class Klassenname : public Basis1, public Basis2
    {

      public: 
        //! Konstruktor, macht dies und das.
        Klassenname( int member1, int member2 );
        //! Methode die etwas macht.
        unsigned int publicMethod( unsigned int a, unsigned int b );
        //! ...
        unsigned int member1() const;
        //! ...
        void setMember1( int m1 );
        //! member2 der Klasse.
        int m_member2;

      private:
        //! Macht etwas.
        void doSomething();
     
    };


    // cpp
    /*!
     *  Ausführliche Beschreibung.
     * \param member1 Beschreibung.
     * \param member2 Beschreibung.
     */
    Klassenname::Klassenname( int member1, int member2 ) : m_member1( member1 ),
                                                                                           m_member2( member2 )
    {
      // Macht etwas.
      doSomething();
    }


    /*!
      * \return member1 der Klasse.
      */
    int Klassenname::member1() const
    {
      return m_member1;
    }


    /*!
      * \param m1 Neuer Wert für member.
      */
    void Klassenname::setMember( int m1 )
    {
      m_member1 = m1;
    }

Re: C/C++ Style-Guide

Verfasst: Fr Mai 06, 2011 5:49 pm
von Kerli
Bei mir würde das in etwa so ausschauen:

Code: Alles auswählen

// -> Header

#ifndef KLASSEN_NAME_HPP_ // maybe also prefixed by NAMESPACE_NAME_
# define KLASSEN_NAME_HPP_

/**
 * Really usefull class which represents just a sample class and really not more
 */
class Klassenname:
  public Basis1,
  public Basis2
{

  public:
  
    /**
     * Initialize class by using member1 for foretell the weather and member2
     * for calulating a really cool number.
     *
     * @param member1
     * @param cool_value
     */
    Klassenname(int member1, int cool_value);
    
    /**
     * Do some public thing...
     *
     * @param a Blah bla
     * @param b Another one...
     * @return The number of atoms your brain consits of
     */
    unsigned int publicMethod(unsigned int a, unsigned int b);
    
    /**
     * Get the $INSERT_DESCRIPTION_OF_MEMBER1_HERE$ (Depending on case just
     * leave description empty)
     *
     * @return Value of $SOME_MORE_DESCRIPTION$
     */
    unsigned int getMember1() const;
    
    /**
     * Set the value of $DESCRIPTION$
     *
     * @remark Do not ever let m1 be 42!!!
     * @param m1 New value...
     */
    void setMember1(int m1);
    
    /**
     * Combined getter and setter
     *
     * @return Reference to member
     */
    int& member1();
    
    // Overloaded getter and setter
    
    /**
     * Setter comment
     *
     * @param m1 asdadasdsadfasf
     */
    void member1(int m1);
    
    /**
     * Getter comment
     * 
     * @return asdlakj jj
     */
    int member1() const;
    
    int _member2; //< Short description
    
    /**
     * Long description Long description Long description Long descri pton asdas
     * Lo ng description Long description Long description Long descrip tion wfa
     */
    int const KONSTANTE_1;

  protected:
  
    unsigned int protectedMethod( unsigned int a, unsigned int b );

  private:
  
    int _member1; //< Blah
    
    /**
     * asdasdkasd
     */
    void doSomething();
    
    /**
     * asjj lkjaskld
     *
     * @param a kjwad asdölkaösdkasd asd
     * @param b aösdköalk sad as
     */
    unsigned int privateMethod(unsigned int a, unsigned int b);
 
};

#endif // KLASSEN_NAME_HPP_

Code: Alles auswählen

// -> Source File

unsigned int g_globalVariable;

// -----------------------------------------------------------------------------
Klassenname::Klassenname(int member1, int cool_value):
  _member1(member1),
  _member2(cool_value)
{
  doSomething();
}

// -----------------------------------------------------------------------------
int Klassenname::member1() const
{
  return _member1;
}

// -----------------------------------------------------------------------------
void Klassenname::setMember(int m1)
{
  _member1 = m1;
}

// -----------------------------------------------------------------------------
unsigned int Klassenname::protectedMethod(unsigned int a, unsigned int b)
{
  // ...
}

// -----------------------------------------------------------------------------
unsigned int Klassenname::privateMethod(unsigned int a, unsigned int b)
{
  // Leerzeilen hier normal nur bei längerem Code.
  unsigned int result;
  int another_local_var = 3;
 
  result = a + b;
 
  return result;
}

// -----------------------------------------------------------------------------
static unsigned int staticFunction( unsigned int a_summand1,
                                    unsigned int a_summand2 )
{
  // Gleiches wie oben.
  unsigned int result;

  result = aSummand1 + aSummand2;
 
  return result;
}
Kommentare
Doxygen Kommentar im Header, da daraus auch die Dokumentation erstellt wird und man sich im Normalfall auch die Header Files zuerst anschaut um zu sehen wie die Klasse funktioniert. Wenn man bereits im Sourcefile nachschauen muss ist es für eine Beschreibung was die Funktion machen sollte sowie so schon zu spät, da es wohl bedeutet dass weder Funktionsname noch Kommentar genau genug beschrieben haben was eigentlich genau passieren soll.

Natürlich kommen auch Kommentar im Sourcefile vor, aber nur solche die für das Verstehen und nicht das Verwenden des Codes nötig sind. Hier verwende ich dann natürlich auch keinen Doxygenkommentare, mit Ausnahme bei Funktionen und Variablen die im Sourcefile definiert werden (also statisch sind). Alles andere braucht keinen Kommentar mehr, da der ja sowieso bereits im Header vorhanden ist.

Präfix
Präfixe verwende ich sehr sparsam. Auf keinen Fall jedoch Präfixe für den Typ (Ungarische Notation). Member bekommen einfach einen Unterstrich als Präfix, da es kurz ist und praktisch für die Auto-Vervollständigung ist, da man nur einen Unterstrich tippen muss und sofort alle Member aufgelistet bekommt. Außerdem kommt es so zu keinen Kollisionen mit Namen für lokale Variablen und Funktionsparameter. Ansonsten bekommen noch globale Variablen, wenn überhaupt welche vorkommen ein g_ davor.

Getter und Setter bekommen ein get- bzw. set-Prefix, um klar zu stellen dass es sich um Getter/Setter handelt. Nicht jeder weiß alle Membernamen um sagen zu können was ein Getter/Setter ist und was nicht. Für boolsche Werte und Flags verwende ich aber durchaus auch is/has/etc. Ausnahmen gibt es aber Vereinzelt auch wie zb x(), y(), z() bei Vektoren...

Groß-/Kleinschreibung
Klassen, Strukturen und allgemein Typen CamelCase, Funktionen firstSmallCamelCase() und Variablen small_with_underscore. Konstanten komplett GROSS, egal ob durch const, define oder enum. Das verhindert komplett Kollisionen zwischen Typ-, Funktions-, Variablen- und Konstantennamen. Makros ebenfalls CAPITALS.