namespace cpp

C++ lernen, kennen, anwenden

Benutzer-Werkzeuge

Webseiten-Werkzeuge


stilrichtlinie

Stilrichtlinie

Wo Inhalt ist, fügen sich die Formen von selbst.
— Leo Tolstoi, Tagebücher, 1896

engl. coding style guide
Meine Festlegungen für die Gestaltung von C++-Quelltexten. Die hier empfohlenen Schreibweisen haben sich für mich als günstig erwiesen. Merke: Richtlinien sind Empfehlungen, kein Dogma. In begründeten Fällen weiche ich vom Standardschema ab. Einige andere Richtlinien zum Vergleich:

Dateiorganisation

Quelltext-Dateinamen enden auf *.cpp, Vorspanndateien (Header) auf *.h. Header erhalten eine Include-Wächter, der sich auf den Namen des Headers bezieht:

//: demo.h : ... Dateikopf-Kommentar
 
#ifndef DEMO_H
#define DEMO_H
 
// ... Abhängigkeiten
#include <...>
 
// ... Inhalte hier
 
#endif // DEMO_H

Jede Datei, auch Header, bezieht die genutzten Definitionen als #include-Anweisung mit ein. Ausnahme: Zirkelbezüge sind durch Forward-Deklaration aufzulösen.

Kommentare

Im Dateikopf werden Dateiname, Autor/Bearbeiter, Anlagedatum und eine Kurzbeschreibung abgelegt. Die Form des des Dateikommentars sollte einheitlich sein, z.B.

//: demo.cpp : Beispielprogramm - R.Richter 2007-07-03
//////////////////////////////////////////////////////

Quellcode sollte soweit wie möglich selbstdokumentierend sein, u.a. durch gut gewählte, "sprechende" Namen für Typen, Funktionen, Variablen und Konstanten. Wiederhole nicht im Kommentar, was schon im Quelltext gesagt ist. Stimmen Quelltext und Kommentar nicht überein, ist vermutlich beides falsch. Erläutere statt dessen, warum der Quelltext so geschrieben wurde:

  for (int t = 3; t <= sqrt(double(n))+0.5; t += 2) // in n==t*y ist t<sqrt(n)<y oder n == t*t
  {
    if (n%t == 0) return false;
  }

Auch Hinweise auf Literatur können angegeben werden:

void farey_series(int n)
{
  // Lit.: D.E.Knuth: DAOCP Vol. 1, Faszikel 1.3', "MMIX", (2002), p. 47.
  ...
}

/**/-Kommentare werden nur selten genutzt, vorwiegend zum Deaktivieren kurzer Codesequenzen während der Entwicklungsphase.

Namenskonventionen

Zwiespalt: Deutsche und englische Namen (Schlüsselwörter) im Gemisch wirken komisch.1) Aber: Nutze die Fremdsprache Englisch nur, wenn Du Dir völlig sicher bist — "false friends" sind peinlich. Nutze ein Wörterbuch, frage einen native speaker.

Klassen und Strukturen

Namen von Klassen und Strukturen beginnen mit Großbuchstaben. Der Rest ist klein geschrieben, bei zusammengesetzten Namen UpperCamelCasing.

class Commander
{ // ...
private:
  int data_;
};

Namen nicht öffentlicher Attribute enden mit einem Unterstrich. Weitere Regeln siehe Variablen.

Methoden und Funktionen

Funktionsnamen werden mit Kleinbuchstaben geschrieben, bei zusammengesetzten Namen camelCasing:

bool istPrimzahl(int n);    

Entscheidungsfragen sollten mit is…(), has…() o.ä. beginnen.

"get"- und "set"-Methoden tragen keine Vorsilbe. Aus dem Aufruf überladener Methoden wird deutlich, was gemeint ist:

  int n = std::cout.precision(); // "getter"
  std::cout.precision(n);        // "setter" 

Parameternamen sollten "sprechend" sein, weiteres siehe Variablen.

Variablen und Konstanten

Für Variablen werden Kleinbuchstaben verwendet, bei zusammengesetzten Namen camelCasing. Konstanten werden mit Großbuchstaben geschrieben, bei zusammengesetzten Namen mit Unterstrichen. Vermeide Unterstriche am Anfang.

const int MAX_ANZAHL = 10;
int anzahlStaubEcken, anzahlStauBecken;
anzahlStaubEcken = 4 * anzahlStauBecken; // rechteckige Becken haben 4 Ecken ;-)

Bei fast gleichen Namen besteht Verwechslungsgefahr, also, wenn möglich, große Sprachdistanz wählen:

anzahlStaubEcken = 4 * anzahlTalsperren; 

Sprechende Namen werden bevorzugt, aber für lokale Variablen, Schleifenzaehler sind kurze Namen zu wählen, eine Art "schwäbische" oder eher "schottische" (?) Notation, z.B.

c Buchstabe (char)
d Dezimalbruch (double)
i Index (int)
n natürliche Zahl (number, int)
u vorzeichenlose Zahl (unsigned int)
p Zeiger (Pointer)
s Zeichenkette (string)
  int sum = 0;
  for (int n = 1; n < MAX_ANZAHL; ++n)
  { 
    sum += n;
  }

ist besser lesbar als

  int summeAllerZahlen = 0;
  for (int natuerlicheZahl = 1; natuerlicheZahl < MAX_ANZAHL; ++natuerlicheZahl)
  {
    summeAllerZahlen += natuerlicheZahl;
  }

Der Kleinbuchstabe l wird wegen seiner Ähnlichkeit zur Zahl 1 vermieden, sofern es nicht der direkten Umsetzung mathematischer Formeln wie $\sigma_{ij} = C_{ijkl} \cdot \varepsilon_{kl}$ dient.

Formatierung

Geschweifte Klammerpaare stehen übereinander, Abschnitte innerhalb des Klammerpaars werden eine Ebene eingerückt (Allman style). Nach meiner Erfahrung sind für Anfänger Blöcke und zusammengehörende Klammern so einfacher erkennbar.

Bevorzugte Editor-Einstellung: Einrückungen erfolgen um zwei Leerzeichen, Tabs werden als Leerzeichen abgespeichert.

class Allman
{
public:
  int f(int n)
  {
    int sum = 0;
    for (int i = 0; i <= n; ++i)
    {
      sum += i;
    }
    return sum;
  }
};

Bei fußgesteuerten Schleifen steht der Kontrollausdruck hinter der schließenden Klammer, nicht darunter:

  do
  {
    something();
  } while (!finished());

Auch Einzelanweisungen von Schleifen und Entscheidungen sind im Klammerblock zu schreiben. Ausnahme: tabellarische Fallunterscheidung.

int istPrimzahl(int n)
{
  if (n < 2)    return false;
  if (n == 2)   return true;
  if (n%2 == 0) return false;
  // ...
}

Leerzeichen dienen der optischen Gliederung innerhalb der Zeile, z.B. vor / nach Operatoren, nach Komma und Semikolon, vor Schleifen- und Entscheidungsbedingungen.

ClangFormat

Vergeude deine kostbare Zeit nicht mit dem "Verschönern" des Quelltextes — dafür gibt es Werkzeuge. Mit ClangFormat werden auch Diskussionen und "Kriege" über die "richtige" Formatierung von Quelltext hinfällig. Die eigene Gestaltungsrichtlinie lässt sich online erstellen und kann als .clang-format-Konfiguration im YAML-Format abgelegt werden:

---
Language: Cpp
AlignConsecutiveAssignments: 'true'
AlignConsecutiveDeclarations: 'true'
AllowShortCaseLabelsOnASingleLine: 'true'
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: 'true'
AllowShortLoopsOnASingleLine: 'true'
AlwaysBreakTemplateDeclarations: 'true'
BreakBeforeBraces: Allman
BreakConstructorInitializersBeforeComma: 'true'
ConstructorInitializerIndentWidth: 2
SpaceBeforeParens: ControlStatements
UseTab: Never
...
1)
Ein Bad-Shop (?) für Sanitär-Einrichtungen (!) existierte nur für kurze Zeit auf der Wallstraße in Dresden. — Warum nur?
stilrichtlinie.txt · Zuletzt geändert: 2017-10-01 14:00 von rrichter