Unterschied: Deklaration, Definition, Initialisierung



  • Hi,
    ich Programmiere jetzt seit über 4 Monaten C++ (aus dem Buch) und habe seit ca. 4 Monaten Unterricht in C.
    Obwohl ich (wie ich meine :D) doch schon relativ viel gelernt habe schleppe ich eine große Frage ständig mit mir herum und die jetzt, da ich meine immer größeren Projekte brav in .h und .ccp Datein aufteile sehr wichtig ist.

    **
    Was ist der Unterschied zwischen definieren, deklarieren und initialisieren.
    **

    In der Schule heißt es immer wir müssen ... Variablen deklarieren.
    Wenn ich das in meinem Buch aber richtig verstanden habe (...:D) dann müsste das so sein:

    static int var=1;
    //static  = Deklaration,
    //int var = Definition,
    //var=1   = Initialisierung
    

    Und wie nennt man das auch bei Funktionen?

    Und mir ist etwas aufgefallen:
    Ich dachte wenn ich eine Variable außerhalb aller Funktion (auch main) deklariere/definiere würde diese Programmglobal sein. Dem ist aber nicht so. Ich kann diese nur mit Hilfe der Speicherklasse extern in eine andere .cpp datei verwenden, warum?



  • Deklaration heisst:
    Dem Compiler sagen, dass es etwas gibt. zB ist

    void foo();
    

    eine Deklaration. Du sagst damit dem Compiler, dass es eine Funktion foo gibt, die void returned und keine Parameter nimmt.

    Definition heisst:
    Dem Compiler sagen, dass er dieses etwas anlegen soll. zB ist

    void foo() { }
    

    eine Definition. Du sagst damit dem Compiler, dass die (bereits bekannte Funktion foo - denn jede Definition impliziert eine Deklaration) exakt so aussieht.

    Initialisierung heisst:
    Dem Compiler sagen, dass er dieses etwas mit einem bestimmten Wert anlegen soll. zB ist

    int i=5;
    

    eine Initialisierung. Du sagst damit dem Compiler, dass die (bereits bekannte Variable i - denn jede Initialisierung impliziert eine Definition, welche ja eine Deklaration impliziert) mit dem Wert 5 vorbegelegt werden soll.

    Um Variablen zu deklarieren braucht man das Schlüsselwort 'extern'.

    So ist zB

    extern int i;
    

    eine Deklaration.

    Aber Achtung:

    extern int i=5;
    

    ist eine Initialisierung. Das extern wird (wenn man so will) ignoriert.

    Eine Variable die als 'extern' deklariert ist, muss natürlich auch irgendwo definiert werden. Dies geschieht meistens in einer anderen Übersetzungseinheit. Es ist das selbe Prinzip wie bei Funktionen.

    class Test {};
    

    ist übrigens auch eine Definition. Die passende Deklaration dazu wäre

    class Test;
    

    Dies führt mich zur ODR (One Definition Rule). Sie besagt, dass jedes Symbol nur einmal definiert werden darf. HumeSikkins erklärt dies auf seiner Homepage sehr schön.

    Als Übung sei dem geneigten Leser folgendes überlassen:

    class Test; //1
    
    class Test {}; //2
    
    int func() { return 7;} //3
    
    extern int i=func(); //4
    
    Test obj(); //5
    

    Die Lösung:

    1. Deklaration
    2. Definition
    3. Definition
    4. Initialisierung
    5. Deklaration


  • Als Ergänzung zu den Beispielen, hier noch eine kurze Definition der drei Begriffe:

    Deklaration:
    Ein Programmausdruck der einen Namen in einen Scope ein- bzw. wiedereinführt.

    Definition:
    Eine Deklaration die die Details einer Entität bekannt macht oder, im Fall von Variablen, die dazu führt, dass Speicher für die Entität reserviert wird.

    Eine Deklaration einer Klasse (struct, class, enum, union) Funktion oder Methode wird zu einer Definition, wenn auf die Deklaration ein in geschweiften Klammern eingeschlossener Block folgt.
    Variablendeklarationen sind immer auch Definitionen es sei denn, der Deklaration ist ein extern vorangestellt.

    Initialisierung:
    Eine Definition mit expliziter Anfangswertzuweisung.



  • krümelkacker schrieb:

    So werden die Begriffe Deklaration und Definition im offiziellen C++ Standard benutzt:

    class foo;          // <-- Deklaration von foo
    
    class foo {         // <-- Definition  von foo
    public:
      int x;            // <-- Definition  von foo::x
      static int y;     // <-- Deklaration von foo::y
      void blah();      // <-- Deklaration von foo::blah
      int get() const { // <-- Definition  von foo::get als inline-Funktion
        return x;
      }
    };
    
    int foo::y;         // <-- Definition  von foo::y
    
    void bar(foo & f);  // <-- Deklaration von bar
    
    void bar(foo & f) { // <-- Definition  von bar
      f.x = 99;
    }
    
    extern int yay;     // <-- Deklaration von yay
    
    int yay;            // <-- Definition  von yay
    
    extern const int t; // <-- Deklaration von t
    
    extern const int t=2; // < Definition  von t
    

    Es gibt aber auch umgangssprachliche Variationen. ZB spricht man bei einer Klassendefinition oft von einer Klassendeklaration. Das hat wahrscheinlich auch mit dem Sprachvorgänger C zu tun, der mit den Begriffen laxer umgeht. Der C Standard verwendet die Begriffe "Deklaration" und "Definition" fast synonym (zumindest im Bezug auf Structs) und spricht lieber von "Funktions-Prototypen" als von "Funktions-Deklarationen".

    Eine Definition ist gleichzeitig auch Deklaration. D.H. Du musst nicht alles vorher deklarieren.

    Innerhalb einer Übersetzungseinheit (ÜE) sind keine Mehrfachdefinitionen erlaubt. Und für "normale" Funktionen und globale Variablen darf es auch Programm-weit nur eine einzige Definition geben. Eine Klassendefinition in einer Header-Datei, die per Textersetzung in mehreren Übersetzungseinheiten eingebunden wird, ist also okay, obwohl es dann mehr als eine Definition geben wird. Neben "normalen" Funktionen gibt es auch Funktions-Templates und Inline-Funktionen, für die es besondere Regeln gibt. Beispielsweise muss eine Inline-Funktion immer in einer ÜE definiert sein, wenn sie da auch benutzt wird. Typischerweise packt man Inline-Funktionen und Funktions-Templates auch in Header-Dateien rein, wenn man sie in mehr als einer ÜE benutzen will.


Anmelden zum Antworten