Logo BKs Home - Ein neuer Versuch. Logo

C++ FAQs

   
C++ makes it much harder to shoot yourself in the foot, but when you do, it blows off your whole leg.
- Bjarne Stroustrup

In C we had to code our own bugs. In C++ we can inherit them.
-Prof. Gerald Karam

    
   

Einleitung
Was hat es mit diesen C++ FAQs aufsich?  updated 

C++ allgemein
Sollte man Variablen zu Beginn eines Blocks deklarieren?save
Was muss man beim Test auf eof() beim Lesen aus C++ Streams beachten?save
Wie lassen sich Speicher- bzw. Ressourcenlöcher vermeiden?save
Was sind auto_ptr und wie setzt man sie ein?save
Was ist falsch an void main() { /* ... */ } bzw. main() { /* ... */ }?save
Wie macht man aus einer Zahl einen String?save
Sollte man <iostream.h> oder <iostream> verwenden?  updated 
Was ist eine using-Deklaration?save
Was ist eine using-Direktive?save
Warum kann man Methoden von Basisklassen nicht in abgeleiteten Klassen überladen?save
Was bedeutet das Schlüsselwort static?save
Was ist der Unterschied zwischen <name.h> und <cname>? 

C++ speziell
Wird für den folgenden Code ein Standardkonstruktor erzeugt? Werden die Member initialisiert?save
Was besagt die one definition rule (ODR)?  updatedsave
Was versteht man unter "Koenig Lookup"?save
Wann wird ein Standardkonstruktor erzeugt? Und was tut er?save
Was ist die Regel der großen Drei (Law of the big three)?save
Wie kann man Strings case-insensitiv vergleichen?save
Wird für T x = u; der Zuweisungsoperator von T aufgerufen?save
Ist Zuweisung nicht trivialer Objekte immer langsamer als Initialisierung?save
Überladen, Überschreiben, Überdecken - Was ist was? 

Anderes
Was ist richtige Vererbung und was hat dies mit dem Liskov-Prinzip zu tun?save
Was ist das open-closed Principle?save
Was ist schlecht an globalen Variablen?save
Wie kann man den Inhalt eines Verzeichnisses auflisten?  updated 
Was ist const-correctness?save
Was ist das Singleton-Pattern und wie wird es in C++ implementiert?save
Was bedeutet "named return value optimization"?save
Wie erhält man richtige Vererbung ohne Liskov-Prinzip?save
Warum sollten Instanzvariablen immer private sein?save



zurück zum Seitenanfang
   Q: Was bedeutet das Schlüsselwort static?

static ist ein Schlüsselwort mit mehreren Bedeutungen. Die konkrete Bedeutung ist abhängig vom Kontext. Prinzipiell kann man zwei Bedeutungen unterscheiden:

  1. Ein Objekt, eine Variable wird genau einmal angelegt. Dabei wird das Objekt/die Variable im statischen Datenbereich erzeugt, nicht wie z.B. lokale Variablen auf dem Stack. In dieser Bedeutung bezieht sich static also auf die Art der Speicherung.
  2. Die zweite Bedeutung bezieht sich auf die Sichtbarkeit eines Namens. static bedeutet hier lokal zu einer bestimmten Übersetzungseinheit bzw. lokal zu einer bestimmten Klasse. Globale Namen sind für den Linker überall sichtbar. Man sagt, sie haben external linkage. static beschränkt in dieser Bedeutung die Sichtbarkeit eines Namens auf eine bestimmte Übersetzungseinheit (internal linkage).

Die erste Bedeutung bezieht sich auf lokale Variablen/Objekte innerhalb von Funktionen. Eine solche statische Variable ist das "Gedächtnis" einer Funktion, da sie ihren Wert auch nach dem Verlassen und bis zum nächsten Funktionsaufruf behält. Dies unterscheidet sie von lokalen Variablen, die auf dem Stack erzeugt und beim Verlassen der Funktion zerstört werden. Statische Variablen werden beim ersten Betreten der Funktion angelegt und, falls nicht anders angegeben, mit dem Nullwert des Typs initialisiert. Für benutzerdefinierte Typen geschieht die Initialisierung, falls nicht anders angegeben, über den Standardkonstruktor. Zerstört werden solche Variablen mit dem Ende des Programms.

Hier ein kleines Beispiel:

void Func()
{
    static int i = 0;
    std::cout    << "Diese Funktion wurde bisher:" << i
                 <<" mal aufgerufen" << std::endl;
    i++;
}

Diese Funktion merkt sich in der Variablen i wie oft sie aufgerufen wurde und schreibt diese Information nach cout.

Wie bereits weiter oben erwähnt, ist ein globaler Name immer in allen Übersetzungseinheiten sichtbar. Wird ein Name auf globaler Ebene mit dem Schlüsselwort static ausgezeichnet, so wird seine Sichtbarkeit auf die aktuelle Übersetzungseinheit beschränkt. Dies hat zum Beispiel den Vorteil, dass solche Namen ohne Probleme in Header-Dateien auftauchen dürfen, ohne dass sich der Linker jemals über ein bereits definiertes Objekt beschweren wird. Allerdings sollte man diese Bedeutung von static in C++ nicht mehr verwenden. Hier gibt es für diesen Zweck die sogenannten anonymen Namensräume (unnamed namespaces). Alle Namen die in einem solchen Namensraum definiert werden, können nur noch innerhalb der Übersetzungseinheit angesprochen werden.

Statt:

static int Global;

Verwendet man in C++ besser:

namespace
{
    int Global;
}

Wichtig: Ein globaler Name wird immer innerhalb des statischen Datenbereichs angelegt. Unabhängig von static. Hier ändert static also nur die Sichtbarkeit, nicht aber den Ort der Speicherung eines Namens.

static in Verbindung mit Klassen erzeugt sogenannte Klassenvariablen/-methoden. Solche können, unabhängig von einem Objekt, über den Namen der Klasse angesprochen werden. Klassenvariablen existieren nur einmal pro Klasse. Sie werden innerhalb der Klassendefinition deklariert und müssen außerhalb dieser definiert werden (normalerweise in der cpp-Datei). Klassenmethode besitzen keinen impliziten this-Zeiger. Sie sind also unabhängig von einem bestimmten Objekt. Sie haben deshalb natürlich aber auch keinen Zugriff auf die Instanzvariablen einer Klasse. static bezieht sich hier sowohl auf die Sichtbarkeit eines Namens, als auch auf dessen Speicherung.

#include <iostream> // Ein-/Ausgabe
using namespace std;
class A
{
    // Achtung: Dies ist nur die Deklaration.
    // Es wird noch kein Speicher belegt.
    static int ObjCount;
    public:
        A() {ObjCount++;}
        ~A() {ObjCount--;}

        static int GeObjCount() {return ObjCount;}

};
// Hier ist die Definition.
int A::ObjCount = 0;

int main()
{
    cout << "Es gibt: " << A::GeObjCount() << " Objekte des TypsA" << endl;
    A a1, a2;
    cout << "Nun gibt es: " << A::GeObjCount() << " Objekte." << endl;
}

Literatur:
  • B. Eckel: "Thinking in C++ Vol. one"

   
   
Ihr Feedback ist mir wichtig:
Wie würden Sie diese Antwort bewerten? Als:     
Haben Sie Fragen, Ergänzungen oder Verbesserungen? Schreiben Sie mir: hume@c-plusplus.de
zurück zum Seitenanfang
    Zuletzt aktualisiert am: 13.01.2007 zurück zur Startseite    
    © Benjamin Kaufmann - Fragen, Kritik und Anregungen bitte direkt an mich oder ins Gästebuch