2010-11-25 3 views
10

Noch eine static Frage.Statisches Schlüsselwort in h-Datei und interne Verknüpfung

Und ich immer noch nicht verstehen, das folgende Verhalten:: Ich habe folgendes gelesen Ich habe eine h Datei:

// StaticTest.h 
#include <stdio.h> 

static int counter = 0; 

struct A { 
    A() { 
     counter++; 
     printf("In A's ctor(%d)\n", counter); 
    } 
    ~A() { 
     counter--; 
     printf("In A's dtor(%d)\n", counter); 
    } 
}; 

static A a; 

Und zwei cpp Dateien:

// StaticTest1.cpp 
#include "StaticTest.h" 

int main() { 
return 0; 
} 

Und:

// StaticTest2.cpp 
#include "StaticTest.h" 

Die Ausgabe des Programms ist:

In A's ctor(1) 
In A's ctor(2) 
In A's dtor(1) 
In A's dtor(0) 

Nun A ‚s Konstruktor zweimal aufgerufen wird, da die h Datei ist zweimal enthalten, und da A 's Instanz mit dem Namen astatic deklariert ist, ist es hat interne Verknüpfung und der Compiler ist glücklich. Da die counter auch als statisch deklariert ist, hat sie auch interne Verknüpfungen, und ich würde erwarten, dass ihr Wert in den zwei cpp Dateien nicht geteilt wird --- aber die Programmausgabe impliziert, dass der Wert geteilt wird, da er bis zu 2 zählt

irgendwelche einblicke?

EDIT: Alle Antworten in Bezug auf, was eine „gute Programmier Gewohnheit“ im Zusammenhang mit der Erklärung der statischen Variablen in h vs. cpp Dateien wird auch begrüßt betrachtet wird.

+0

Ich mag * * etwas über Implementierungsdetails sagen und kompilieren Zeit initialisierte statische Werte im Vergleich zu Laufzeit initialisiert statische Werte, aber ich bin nicht zuversichtlich, es als Antwort zu veröffentlichen. Versuchen Sie, 'counter' nicht initialisiert zu lassen und initialisieren Sie es in' main() '. –

+0

@ Benoit Thiery: Dies ist der vollständige Quellcode. –

+0

@ Ignacio Vazquez-Abrams: von MSDN-Seite: "Wenn Sie eine Variable deklarieren, hat die Variable statische Dauer und der Compiler initialisiert es auf 0, außer Sie einen anderen Wert angeben" –

Antwort

9

Wenn StaticTest.h zwischen verschiedenen Quelldateien gemeinsam genutzt wird, wird das Verhalten nicht definiert.

Wenn Sie eine Klassen- oder Inline-Funktion in verschiedenen Übersetzungseinheiten definieren, müssen ihre Definitionen übereinstimmen (dieselbe Sequenz von Token) und alle Identifikatoren müssen sich auf dieselbe Entität beziehen (außer const Objekt mit interner Verknüpfung) wie in der Definition in einer anderen Übersetzungseinheit.

Sie verletzen dies, weil counter interne Verknüpfung hat, so dass in verschiedenen Übersetzungseinheiten der Bezeichner in den Funktionsdefinitionen auf ein anderes Objekt verweist.

Referenz: C++ 03 3.2 [basic.def.odr]/5.

+1

+1 C++ ist eine schwierige Sprache :) –

+1

Ich bin mir nicht sicher, ob ich deine Antwort vollständig verstehe - 'counter' ist keine Klassendefinition, es ist eine Variablendeklaration, und trotzdem ist interne Verknüpfung nicht möglich zwei Entitäten haben, jeder in seiner eigenen Übersetzungseinheit? –

+3

@Itamar Katz: Ja, Sie haben mehr als eine Entität namens 'counter' (jede mit interner Verknüpfung), aber Sie verletzen die ODR bei der Definition von' A', 'A :: A' und' A :: ~ A'. Obwohl Ihre Definitionen aus den gleichen Token-Folgen bestehen (gut), weil 'counter' eine interne Verknüpfung hat, bezieht sich die Verwendung dieses Identifikators in der Definition von 'A' auf ein anderes Objekt in jeder einzelnen Übersetzungseinheit. Dies bedeutet, dass die Definitionen von "A" über Übersetzungseinheiten hinweg nicht gleich sind, was die ODR verletzt. –

Verwandte Themen