Include-Guard

aus Wikipedia, der freien Enzyklopädie
(Weitergeleitet von Include Guard)
Wechseln zu: Navigation, Suche

Der Include Guard oder Include-Wächter ist eine Programmiertechnik, um in C und C++ das Problem der mehrfachen Einbindung zu lösen.

Dieses Problem tritt auf, wenn innerhalb einer Übersetzungseinheit mehrmals die gleiche Header-Datei eingebunden wird. Das geschieht in der Regel unbeabsichtigt, z. B. wenn mehrere Header-Dateien die gleiche Bibliothek benutzen.

Beispiel einer Mehrfacheinbindung[Bearbeiten]

// A.h
const int M = 123;
 
class A
{ /* ... */ };


// B.h
#include "A.h"
 
class B : public A
{ /* ... */ };

Im Hauptprogramm soll nun sowohl die Klasse A als auch B genutzt werden:

  1. // program.cpp
    
  2. #include "A.h"
    
  3. #include "B.h"
    
  4.  
    
  5. int main() { /* ... */ }
    

Das Programm ist fehlerhaft, weil die Klasse A doppelt definiert wird: Die erste Definition erfolgt beim Einbinden der Headerdatei A.h in Zeile 2. Die zweite Definition erfolgt, weil die Headerdatei B.h, die in Zeile 3 eingebunden wird, selbst wiederum A.h einbindet. Die Klasse (und ggf. weitere Variablen) aus dieser Datei wurden bereits zuvor definiert, was zu einem Fehler führt.

Lösung mit Präprozessor-Makros (#ifndef)[Bearbeiten]

Der #ifndef-Wrapper ist der traditionelle und C-konforme Ansatz. Das Problem der Mehrfacheinbindung wird durch Definition eines eindeutigen Präprozessor-Makros beim ersten Einbinden der Header-Datei gelöst. War das Makro bereits definiert, werden die nachfolgenden Definitionen des Headers übersprungen:

// A.h
#ifndef _A_H_
#define _A_H_
 
class A
{ /* ... */ };
 
#endif /* _A_H_ */

Im obigen Beispiel bewirkt das, dass beim erstmaligen Einbinden von A.h (aus program.cpp) das Makro _A_H_ noch nicht definiert ist und der Präprozessor die Definitionen durchläuft. Beim zweiten Einbinden (aus B.h) ist das Makro bereits definiert und der Präprozessor überspringt den #ifndef … #endif-Block.

Da Makros im globalen Namensraum existieren, kann es hier zu Problemen kommen, wenn versucht wird, den gleichen Name an anderer Stelle zu verwenden. Dem kann durch die Festlegung von Namenskonventionen zwar vorgebeugt werden, es löst das Problem dennoch nicht[1].

Der CPP, der Präprozessor der GCC, erkennt solche Konstrukte automatisch, merkt sich die entsprechenden Dateien und überspringt diese bei nochmaligem Einbinden[2].

Lösung über Spracherweiterungen (#pragma once)[Bearbeiten]

Die meisten gebräuchlichen C++-Compiler unterstützen heute die Spracherweiterung #pragma once. Diese sorgt ebenfalls dafür, dass eine (Header-)Datei nur einmal eingebunden wird, setzt jedoch auf höherer Ebene an (direkt am Präprozessor) und führt auch keine Makros in den globalen Namensraum ein.

Zur Verwendung genügt es, innerhalb der Header-Datei die Präprozessordirektive #pragma once einzufügen:

// A.h
#pragma once
 
class A
{ /* ... */ };

Diese Spracherweiterung wird von den folgenden C++-Implementierungen unterstützt:

Einzelnachweise[Bearbeiten]

  1. Eric Fleegal's WebLog on MSDN Blogs. Abgerufen am 19. August 2011.
  2. Once-Only Headers im GNU CPP Online Manual. Abgerufen am 19. August 2011.
  3. GCC 3.4 Release Series − Changes, New Features, and Fixes. Abgerufen am 16. Mai 2014.
  4. clang: Pragma.cpp Source File. Abgerufen am 16. Mai 2014.
  5. MS Developer Network − once (C/C++). Abgerufen am 16. Mai 2014.
  6. Comeau C++ 4.0Pre-Release − User-Documentation: Pragmas. Abgerufen 16. Mai 2014.
  7. #pragma once - RAD Studio XE3. Abgerufen am 16. Mai 2014.
  8. Pragmas #pragma once. Abgerufen am 16. Mai 2014.