Einführung in getrennte Übersetzung in C++ im Rahmen der Lehre des Programmierens mit der Programmiersprache C++. [] (C++ getrennte Compilierung C++ Include-Guard C++), Lektion, Seite 721231
https://www.purl.org/stefan_ram/pub/c++_getrennte_uebersetzung_de (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram
C++-Kurs

Getrennte Übersetzung in C++

Teile einer Übersetzungseinheit, die gemeinsam eine bestimmte Aufgabe erledigen, können von dieser in eine weitere Übersetzungseinheit abgetrennt werden. Das ist so üblich und verbessert die Übersicht, wenn jede Übersetzungseinheit einen klar definierten Zuständigkeitsbereich hat. Es erlaubt außerdem, eine Übersetzungseinheit in verschiedenen Projekten (z.B. Programmen) zu verwenden und so einmal  investierte Arbeit mehrfach  zu nutzen.

Dieses Vorgehen soll zunächst an einem einfachen Beispiel gezeigt werden.

monolith.cpp
#include <iostream> // ::std::cout 
#include <ostream> // <<
void hallo(){ ::std::cout << "Hallo, "; }
int main(){ ::hallo(); ::std::cout << "Peter!\n"; }

::std::cout
Hallo, Peter!

Es kann der Eindruck entstehen, daß die Funktion zur Ausgabe von "Hallo, " eine eigene Übersetzungseinheit verdient, weil sie in mehreren Projekten verwendet werden könnte. (In der Praxis wäre sie dafür meist zu klein, doch bleibt das Beispiel so zunächst überschaubar. In Anwendungsprojekten sind die Übersetzungseinheiten oft größer.)

Eine mögliche Zerlegung—noch nicht ganz perfekt—besteht aus der Übersetzungseinheit "hallo.cpp" und der Übersetzungseinheit "main.cpp".

hallo.cpp
#include <iostream> // ::std::cout 
#include <ostream> // <<
void hallo(){ ::std::cout << "Hallo, "; }

Konsole
Compile succeeded.

main.cpp
#include <iostream> // ::std::cout 
#include <ostream> // <<
int main(){ ::hallo(); ::std::cout << "Peter!\n"; }

Konsole
"main.c", line 3: error: the global scope has no "hallo" 
int main(){ ::hallo(); ::std::cout << "Peter!\n"; } 
^
1 error detected in the compilation of "main.c".

Die Übersetzungseinheit "main.cpp" kann nicht übersetzt werden, weil der Bezeichner "hallo" im globalen Namensbereich nicht bekannt ist. Das Problem kann durch eine Deklaration  des Bezeichners behoben werden. Durch die Deklaration wird dem Übersetzer zugesichert, daß ein Bezeichner "hallo" für eine Funktion (ohne Ergebnis und Parameter) im globalen Namensbereich definiert wird. Auch wenn der Übersetzer die Definition nicht kennt, ist ihm dann der Typ bekannt (nach dem Motto “trust the programmer ”) und das genügt.

main.cpp
#include <iostream> // ::std::cout 
#include <ostream> // <<
void hallo();
int main(){ ::hallo(); ::std::cout << "Peter!\n"; }

Konsole
Compile succeeded.

Das Programm läuft nun noch nicht, aber beide Übersetzungseinheiten konnten zunächst in Zwischendateien (die Objektdateien ) übersetzt werden.

Die erzeugten Zwischendateien müssen nun zu einem lauffähigen Programm verbunden werden, wobei der Bezug auf die Funktion "::hallo" aufgelöst werden muß (Beim Aufruf der Funktion "::hallo" muß die Definition aus einer anderen Objektdatei aufgerufen werden.). Zum Auflösen des Bezugs muß ein Verbinder aufgerufen werden. Wie genau dieser Verbinder bedient wird, hängt vom verwendeten Betriebssystem und Entwicklungssystem ab, es ist nicht durch die Programmiersprache C++  festgelegt. Da es hierfür viele verschiedene Möglichkeiten gibt, muß hierfür die Anleitung des verwendeten Entwicklungssystems herangezogen werden. Das Vorgehen zur Aktivierung dieser Verbindung kann daher nicht in dieser Lektion beschrieben werden. Nach dem Verbinden ist dann ein lauffähiges Programm entstanden, das die Zeile "Hallo, Peter!" ausgibt.

::std::cout
Hallo, Peter!

Es könnte nun noch eine andere Übersetzungseinheit "main1.cpp" mit einer Funktion "main" definiert werden, die mit der Übersetzungseinheit "hallo.cpp" verbunden werden kann, um ein weiteres ausführbares Programm zu erzeugen.

main1.cpp
#include <iostream> // ::std::cout 
#include <ostream> // <<
void hallo(); // Eine weitere Kopie der Deklaration
int main(){ ::hallo(); ::std::cout << "Susanne!\n"; }

Konsole
Compile succeeded.

::std::cout
Hallo, Susanne!

Das vorgestellte Verfahren hat aber noch Mängel: Wenn die Übersetzungseinheit "hallo.cpp" tatsächlich in mehreren Projekten verwendet werden sollte, dann muß die Deklaration der Funktion "hallo" in jeder Klienten-Übersetzungseinheit stehen. Es entstünden also viele Kopien. Bei den häufigen größeren Übersetzungseinheiten mit mehreren Funktionen müßten sogar mehrere Funktionsdeklarationen in jeden Klienten (Benutzer) kopiert werden. Außerdem kann der Übersetzer nicht prüfen, ob die Deklaration der Funktion "hallo" mit der Definition verträglich ist.

Um das unnötige Kopieren von Deklarationen zu verhindern, wird diese nun traditionell einmal in eine Datei geschrieben, die dann mit einer Vorverarbeiter-Direktive am „Kopf“ (Anfang) aller Klienten eingefügt wird und daher auch als „Kopfdatei“ (header ) bezeichnet wird. Diese Datei enthält die Deklarationen  der Bezeichner einer Übersetzungseinheit, die in anderen Übersetzungseinheiten verwendet werden können, und weiteres Material, das der Übersetzer sehen muß, damit eine Einheit verwendet werden kann. Solch eine Kopfdatei hat oft die Dateinamenserweiterung ".h" oder die Dateinamenserweiterung ".hpp" und heißt sonst wie die zugehörige Übersetzungseinheit (ohne die Erweiterung ".cpp"). In dem hier verwendeten Beispiel enthält die Kopfdatei "hallo.h" die Deklaration der Funktion "hallo".

hallo.h
#ifndef hallo_h_INCLUDED_20030115 
#define hallo_h_INCLUDED_20030115
void hallo();
#endif

Alle Zeilen in einer Kopfdatei werden Bestandteil jeder Datei, in die sie eingefügt wird, also ihres Klienten. Daher sollte der Autor einer Kopfdatei nur das unbedingt Nötige in sie aufnehmen.

Allgemein gesagt, müssen alle Informationen, die der Compiler bei der Übersetzung sehen muß, in die Kopfdatei  geschrieben werden, alles andere gehört in die Implementationsdatei. Einem Anfänger fehlt aber oft noch die nötig Vorstellung von den Vorgängen bei der Herstellung, um dieses Kriterium immer richtig anzuwenden, daher können folgende Regelungen beachtet werden: Deklarationen  und Klassenspezifizierer  kommen in die Kopfdatei, Definitionen  in die Implementationsdatei. Makrodefinitionen  kommen dann in die Kopfdatei, wenn sie von Klienten gesehen werden sollen. Einzureihende  Funktionsdefinitionen gehören auch in die Kopfdatei, using -Deklarationen oder using -Direktiven sollten in Kopfdateien nicht verwendet werden, da sie sonst in den Klienten wirksam werden, was fast immer unerwünscht ist.

Nun kann jeder Klient der Dienste (wie beispielsweise der Funktionen) der Übersetzungseinheit "hallo.cpp" alle benötigten Deklarationen mit einer Einfügedirektive (Kopfdirektive) einfügen (inkludieren).

main2.cpp
#include <iostream> // ::std::cout 
#include <ostream> // <<
#include "hallo.h"
int main(){ ::hallo(); ::std::cout << "Peter!\n"; }

Konsole
Compile succeeded.

::std::cout
Hallo, Peter!

Man kann sich vorstellen, daß die Standardkopfdirektiven, wie "#include <iostream>" auch auf das Einfügen solcher Kopfdateien zurückgehen. Bei den Standardkopfdirektiven werden die Namen jedoch in spitze Klammern "<>" statt in Anführungszeichen geschrieben und es wurde inzwischen festgelegt, daß sie nicht mehr unbedingt Dateien im wörtlichen Sinne bereitstellen, sondern es reicht, wenn der Übersetzer sie erkennt und daraufhin die entsprechenden Deklarationen so bereitstellt, als ob eine entsprechende Kopfdatei eingefügt worden sei. Zum besseren Verständnis kann man sich dabei aber vorstellen, daß diese Standarddirektiven Kopfdateien mit Deklarationen für Standardbezeichner, wie den Bezeichner "::std::cout", einfügen, so daß diese dann verwendet werden können, auch wenn sie in einer Übersetzungseinheit nicht definiert werden.

Eine Übersetzungseinheit, wie die Übersetzungseinheit "hallo.cpp", zusammen mit ihrer Kopfdatei, wie die Kopfdatei "hallo.h" kann man insgesamt als ein Modul  ansehen, das bestimmte Dienste anbietet. Perfekt wird solch ein Modul dann mit einer Dokumentationsdatei, die auch noch erklärt, wie diese Dienste benutzt werden können. Zur Herstellung solch einer Dokumentationsdatei können Dokumentationskommentare in der Kopfdatei verwendet werden. Man kann dann auch schön erkennen, wie die Kopfdatei eine Schnittstelle  beschreibt (Sicht von außen) und die cpp -Datei die Implementation  (Sicht von innen), weswegen sie auch Implementationsdatei  genannt wird.

In die Implementationsdatei des Moduls wird die Kopfdatei auch noch einmal eingefügt, weil es dem Übersetzer dann auffallen würde, wenn die Deklarationen mit dem Typ der definierten Entitäten nicht verträglich wären und eine entsprechende Fehlermeldung erzeugt werden würde. Außerdem benötigt die Implementationsdatei oft selber auch bestimmten Informationen aus der Kopfdatei.

hallo3.cpp
#include <iostream> // ::std::cout 
#include <ostream> // <<
#include "hallo3.h"
void hallo3(){ ::std::cout << "Hallo, "; }

hallo3.h
#ifndef hallo3_h_INCLUDED_20030115 
#define hallo3_h_INCLUDED_20030115
/** @file hallo3.h 
@brief Unterstuetzung bei der Ausgabe von "Hallo, ". */
/// Ausgabe des Textes "Hallo, " 
void hallo3();
#endif

hallo3.txt [Dokumentation]
hallo3.h Dateireferenz 
Unterstuetzung bei der Ausgabe von "Hallo, ". 
Funktionen  
void hallo3()  
Ausgabe des Textes "Hallo, ".

hallo3_ec.cpp
/** @file hallo3_ec.cpp 
@brief Testklient des Moduls hallo3. */
#include <iostream> // ::std::cout 
#include <ostream> // <<
#include "hallo3.h"
int main(){ ::hallo3(); ::std::cout << "Peter!\n"; }

Konsole
Compile succeeded.

::std::cout
Hallo, Peter!

Man darf aber nicht glauben, die Programmiersprache C++  habe einen bestimmten Begriff von einem Modul. Ein Modul ist lediglich eine bestimmte etablierte Art der Verwendung von C++, es wird aber nicht speziell durch C++  unterstützt, sondern vom Programmierer aus verschiedenen C++ -Sprachelementen zusammengebastelt. Es handelt sich als um eine bestimmte tradierte Art der Verwendung von C++  aber nicht um einen Begriff der Sprache selber. In diesem Sinne gilt „Es gibt in C++  keine Module.“ Es ist lediglich eine Entscheidung des Programmierers und dieses Textes eine Implementationsdatei (wie die Datei "hallo3.cpp") und eine Kopfdatei (wie die Datei "hallo3.h") mit der dazugehörigen Dokumentationsdatei (wie der Datei "hallo3.txt") zusammen gedanklich als ein Modul "hallo3" aufzufassen.

Die Dokumentationsdatei und die Schnittstellendatei eines Moduls müssen so geschrieben werden, daß diesen beiden Dateien alle Informationen zur Benutzung des Moduls entnommen werden können, ohne daß es nötig ist, auf die Implementationsdatei zurückzugreifen. Im Allgemeinen sollten alle zur Verwendung eines Moduls nötigen Informationen der Dokumentation entnommen werden können.

Wenn ein Bezeichner von einem Modul definiert wird und mit dieser Definition anderen Übersetzungseinheiten zur Verfügung gestellt wird, sagt man auch, der Bezeichner werde exportiert  oder er habe externe Verbindung (external linkage ). Soll eine Funktionsdefinition von anderen Übersetzungseinheiten aus nicht  erreichbar sein, so kann sie als Schlüsselwortes "static" gekennzeichnet werden. Man sagt dann auch, diese Definition sei von anderen Übersetzungseinheiten aus nicht sichtbar  und der definierte Bezeichner habe interne Verbindung (internal linkage ). Bezeichner mit interner Verbindung werden ihrer Sichtbarkeit entsprechend auch nicht in der Kopfdatei deklariert. Ein Beispiel dafür findet sich im Programm "hallo4.cpp". Jedoch sollte diese Verwendung des Schlüsselwortes "static" vermieden werden, weil es für denselben Zweck bessere Mittel gibt.

Getrennte Kompilierung
Schreiben Sie ein Modul "englisch", das die Funktion "vielleicht" enthält. Diese Funktion soll das Englische Wort für „vielleicht“ (das Wort "perhaps") ausgeben. Schreiben Sie einen Testklienten als weitere Übersetzungseinheit und benutzen sie darin das Modul "englisch", um das englische Wort für „vielleicht“ auszugeben. Im Testklienten muß danach auch noch ein Zeilenende ausgegeben werden, bevor das Programm endet.

Getrennte Übersetzung von Klassen

Viele C++ -Programme machen umfangreichen Gebrauch von Klassen. Dabei werden zusammengehörige Klassen innerhalb einer Übersetzungseinheit definiert.

Die in einer anderen Lektion definierten Klassen zur Ausgabe von Liedern können jeweils in eine eigene Datei geschrieben werden. Dadurch wird kann das unübersichtliche große Programm in übersichtliche kleine Übersetzungseinheiten aufgeteilt werden. Beide Liedklassen könnten gemeinsam in einem Lieder-Modul definiert werden. In dieser Lektion werden jedoch beide Lieder in jeweils eine eigene Datei geschrieben. (Diese Dateien könnten dann übersichtlich in einem Lieder-Verzeichnis zusammengefaßt werden.)

Der Klassenspezifizierer wird in die Kopfdatei des Moduls geschrieben. Die Definition der Elemente der Klasse erfolgt in der Implementationsdatei. Wie zuvor bereits erwähnt, sind die drei erzeugten Objektdateien miteinander zu verbinden, um ein lauffähiges Programm zu erzeugen.

Jede Implementationsdatei braucht nur ihre eigene Kopfdatei einzufügen. Der Testklient benötigt beide Kopfdateien, da er beide Klassen benutzen will.

Die Kopfdateien enthalten selber den Bezeichner "::std::cout" oder den Operator "<<" nicht, deren Verwendung die Direktive "#include <iostream>" bzw. die Direktive "#include <ostream>" nötig machen würde. Daher treten diese Direktiven in den Kopfdateien auch nicht auf. Das ist so auch besser, da der Klient sonst ebenfalls diese Direktiven enthalten würde, was aber nicht immer erwünscht ist.

kuckuck.h
#ifndef kuckuck_h_INCLUDED_20030115 
#define kuckuck_h_INCLUDED_20030115
/** @file kuckuck.h 
@brief Das Lied "Auf einem Baum ein Kuckuck sass" */
/// Das Lied "Auf einem Baum ein Kuckuck sass" 
struct kuckuck  
{ /// Das Lied ausgeben 
static void ausgeben();  
/// Refrain des Liedes ausgeben 
static void refrain(); };
#endif

kuckuck.cpp
#include <iostream> 
#include <ostream>
#include "kuckuck.h"
void ::kuckuck::refrain() 
{ ::std::cout << "Sim sa la dim, bam ba,\n"; 
::std::cout << "Sa la du, sa la dim -\n"; }
void ::kuckuck::ausgeben() 
{ { ::std::cout << "Auf einem Baum ein Kuckuck, -\n"; refrain(); 
::std::cout << "Auf einem Baum ein Kuckuck sass.\n"; } 
{ ::std::cout << "Da kam ein junger Jaeger, -\n"; refrain(); 
::std::cout << "Da kam ein junger Jaegersmann.\n"; } 
{ ::std::cout << "Der schoss den armen Kuckuck, -\n"; refrain(); 
::std::cout << "Der schoss den armen Kuckuck tot.\n"; }}

vogel.h
#ifndef vogel_h_INCLUDED_20030115 
#define vogel_h_INCLUDED_20030115
/** @file vogel.h 
@brief Das Lied "Vogelhochzeit" */
/// Das Lied "Ein Vogel wollte Hochzeit machen" 
struct vogel 
{ /// Das Lied ausgeben 
static void ausgeben();  
/// Refrain des Liedes ausgeben 
static void refrain(); };
#endif

vogel.cpp
#include <iostream> // ::std::cout 
#include <ostream> // <<
#include "vogel.h"
void ::vogel::refrain() 
{ ::std::cout << "Fi-di-ra-la-la, fi-di-ra-la-la, fi-di-ra-la-la-la-la!\n"; }
void ::vogel::ausgeben() 
{ { ::std::cout << "Ein Vogel wollte Hochzeit machen, in dem gruenen Walde.\n"; 
refrain(); } 
{ ::std::cout << "Die Drossel war der Braeutigam, die Amsel war die Braute.\n"; 
refrain(); } 
{ ::std::cout << "Die Lerche, die Lerche, die fuehrt die Braut zur Kerche.\n"; 
refrain(); }}

lieder_ec.cpp
#include <iostream> // ::std::cout 
#include <ostream> // <<
#include "kuckuck.h" 
#include "vogel.h"
/// Beispielklient 
int main() 
{ ::kuckuck::ausgeben(); ::vogel::ausgeben(); }

::std::cout
Auf einem Baum ein Kuckuck, - 
Sim sa la dim, bam ba, 
Sa la du, sa la dim - 
Auf einem Baum ein Kuckuck sass. 
Da kam ein junger Jaeger, - 
Sim sa la dim, bam ba, 
Sa la du, sa la dim - 
Da kam ein junger Jaegersmann. 
Der schoss den armen Kuckuck, - 
Sim sa la dim, bam ba, 
Sa la du, sa la dim - 
Der schoss den armen Kuckuck tot. 
Ein Vogel wollte Hochzeit machen, in dem gruenen Walde. 
Fi-di-ra-la-la, fi-di-ra-la-la, fi-di-ra-la-la-la-la! 
Die Drossel war der Braeutigam, die Amsel war die Braute. 
Fi-di-ra-la-la, fi-di-ra-la-la, fi-di-ra-la-la-la-la! 
Die Lerche, die Lerche, die fuehrt die Braut zur Kerche. 
Fi-di-ra-la-la, fi-di-ra-la-la, fi-di-ra-la-la-la-la!

using -Deklaration und using -Direktive *

Eine using -Deklaration (beginnend mit dem Schlüsselwort "using" ohne direkt folgendes Schlüsselwort "namespace") oder using -Direktive (beginnend mit dem Quelltext "using namespace") mit Namensraum-Gültigkeitsbereich sollte in einer Kopfdatei nicht enthalten sein, da sie dann auch für alle Klienten gelten würde. Daher sollten die Bezeichner in Kopfdateien immer mit vorangestelltem Namensraum geschrieben werden oder der Gültigkeitsbereich der verwendeten using -Deklarationen oder using -Direktiven muß so eingeschränkt werden, daß diese nicht mehr für Klienten gelten, beispielsweise indem diese in einem Block verwendet werden.

Makrodefinitionen *

Makros muß der Übersetzer (genauer: der Vorverarbeiter) samt ihrer Definition kennen, damit er sie richtig verwenden kann. Deswegen müssen sie in der Kopfdatei eines Moduls definiert  werden, wenn sie im Klienten verwendet werden sollen. Dadurch können Implementationsdetails sichtbar werden, die nicht sichtbar werden sollten. (Ein Klient könnte sich an diese binden, was ihre Änderbarkeit verringert.) Daher sollten Makros möglichst vermieden werden. Das folgende Beispiel zeigt wie ein Modul ein Makro exportiert.

hallo4.cpp
// keine Implementationsdatei noetig

hallo4.h
#ifndef hallo4_h_INCLUDED_20030115 
#define hallo4_h_INCLUDED_20030115
/// Ausgabe des Textes "Hallo, " (Makroversion) 
#define HALLO4 { ::std::cout << "Hallo, "; }
#endif

hallo4.txt [Dokumentation]
hallo4.h Dateireferenz 
Makrodefinitionen 
#define HALLO4 { ::std::cout << "Hallo, "; }  
Ausgabe des Textes "Hallo, " (Makroversion).

main4.cpp
#include <iostream> // ::std::cout 
#include <ostream> // <<
#include "hallo4.h"
int main() 
{ HALLO4 ::std::cout << "Michael!\n"; }

Konsole
Compile succeeded.

::std::cout
Hallo, Michael!

Definitionen einzureihender Funktionen außerhalb einer Klasse *

Einzureihende Funktionen (inline -Funktionen) muß der Übersetzer samt ihrer Definition kennen, damit er sie richtig verwenden kann. Deswegen müssen sie in der Kopfdatei zu einer Übersetzungseinheit nicht nur deklariert, sondern sogar vollständig definiert  werden. Das weicht leider von der schönen Grundregel ab, die empfiehlt, daß die Kopfdatei nur die Schnittstelle  eines Moduls enthält und die Implementationsdatei die Definitionen und ist daher auch ein Nachteil einzureihender Funktionen. Dadurch, daß der Klient aus der Kopfdatei Interna der Definition erfahren könnte, kann er sich an diese Binden und es dadurch erschweren, diese bei Bedarf zu ändern.

Das folgende Beispiel zeigt, wie ein Modul eine einzureihende Funktion exportiert.

hallo5.cpp
// keine Implementationsdatei noetig

hallo5.h
#ifndef hallo5_h_INCLUDED_20030115 
#define hallo5_h_INCLUDED_20030115
/** @file hallo5.h 
@brief Unterstuetzung bei der Ausgabe von "Hallo, ". */
/// Ausgabe des Textes "Hallo, " (einzureihende Funktion) 
inline void hallo5(){ ::std::cout << "Hallo, "; }
#endif

hallo5.txt [Dokumentation]
hallo5.h Dateireferenz 
Funktionen 
void hallo5() [inline] 
Ausgabe des Textes "Hallo, " (einzureihende Funktion).

main5.cpp
#include <iostream> // ::std::cout 
#include <ostream> // <<
#include "hallo5.h"
int main(){ ::hallo5(); ::std::cout << "Susanne!\n"; }

Konsole
Compile succeeded.

::std::cout
Hallo, Susanne!

Definitionen einzureihender Funktionen innerhalb einer Klasse *

Einzureihende Funktionen (inline -Funktionen) muß der Übersetzer samt ihrer Definition kennen, damit er sie richtig verwenden kann. Deswegen müssen sie in der Kopfdatei zu einer Übersetzungseinheit nicht nur deklariert, sondern sogar vollständig definiert  werden. Das weicht leider von der schönen Grundregel ab, die empfiehlt, daß die Kopfdatei nur die Schnittstelle  eines Moduls enthält und die Implementationsdatei die Definitionen und ist daher auch ein Nachteil einzureihender Funktionen. Das folgende Beispiel zeigt, wie ein Modul eine einzureihende Funktion exportiert.

Um eine einzureihende Funktion als Mitglied einer Klasse zu definieren, gibt es zwei Möglichkeiten.

Die letztgenannte Schreibweise ist vorzuziehen, da der Klassenspezifizierer übersichtlicher ist, wenn er nur reine Deklarationen enthält.

Einzureihende Funktionen einer Klasse vergrößern die Kopplung zwischen der Klasse und ihren Klienten und mindern die Kapselung. Deswegen sollten sie nur verwendet werden, wenn diesem Nachteil ein entsprechender Vorteil durch ihre Verwendung entgegensteht.

Im Normalfall sollten Definitionen in der Implementationsdatei stehen—der Klassenspezifizierer sollte nur reine Deklarationen enthalten. Einzureihende Funktionen, also auch innerhalb des Klassenspezifizierers definierte Funktionen, sollten die Ausnahme sein.

hallo6.cpp
// keine Implementationsdatei noetig

hallo6.h
#ifndef hallo6_h_INCLUDED_20030115 
#define hallo6_h_INCLUDED_20030115
/** @file hallo6.h 
@brief Zwei Funktionen zur Ausgabe von "Hallo, " */
/// Funktionen zur Ausgabe von "Hallo, " 
struct hallo6 
{ /// Ausgabe des Textes "Hallo, " (einzureihende Funktion) 
static void hallo6a(){ ::std::cout << "Hallo, "; } 
/// Ausgabe des Textes "Hallo, " (einzureihende Funktion) 
static void hallo6b(); };
inline void hallo6::hallo6b(){ ::std::cout << "Hallo, "; }
#endif

hallo6.txt [Dokumentation]
hallo6.h Dateireferenz 
Funktionen 
void hallo6a() [inline] 
Ausgabe des Textes "Hallo, " (einzureihende Funktion).  
void hallo6b() [inline] 
Ausgabe des Textes "Hallo, " (einzureihende Funktion).

main6.cpp
#include <iostream> // ::std::cout 
#include <ostream> // <<
#include "hallo6.h"
int main() 
{ ::hallo6::hallo6a(); ::std::cout << "Michael!\n";  
::hallo6::hallo6b(); ::std::cout << "Katharina!\n"; }

Konsole
Compile succeeded.

::std::cout
Hallo, Michael! 
Hallo, Katharina!

Definitionen mit interner Bindung *

Eine Funktionsdefinition kann mit dem Deklarationsspezifizierer "static" gekennzeichnet werden. Der definierte Bezeichner hat dann interne Bindung. Das bedeutet, daß er nur innerhalb der die Definition enthaltenden Übersetzungseinheit sichtbar ist. Aus einer anderen Übersetzungseinheit ist dieser Bezeichner also nicht mit der definierten Bedeutung sichtbar. (Er könnte in anderen Übersetzungseinheiten allerdings ebenfalls definiert werden.)

In C++  wird für die Definition von Bezeichnern mit Dateigültigkeitsbereich, die nur innerhalb einer Übersetzungseinheit verwendet werden sollen, allerdings ein anderes Vorgehen unter Verwendung eines anonymen Namensraums empfohlen, das aber nicht in dieser Lektion behandelt wird. Deswegen soll diese Verwendung des Schlüsselworts "static" vermieden werden. Sie wird hier nur der Vollständigkeit halber vorgestellt, aber nicht empfohlen.

hallo7.h
#ifndef hallo7_h_INCLUDED_20030115 
#define hallo7_h_INCLUDED_20030115
/** @file hallo7.h 
@brief Eine Funktion zur Ausgabe von "Hallo, " */
/// Ausgabe des Textes "Hallo, ". 
void hallo4(); // Deklaration einer Funktion mit externe Verbindung
#endif

hallo7.cpp
#include <iostream> // ::std::cout 
#include <ostream> // <<
#include "hallo7.h"
static void hallo4_impl() // interne Verbindung 
{ ::std::cout << "Hallo, "; }
void hallo4() // externe Verbindung 
{ ::hallo4_impl(); }

hallo7.txt [Dokumentation]
hallo7.h Dateireferenz 
Funktionen 
void hallo7() 
Ausgabe des Textes "Hallo, ".

main7.cpp
#include <iostream> // ::std::cout 
#include <ostream> // <<
#include "hallo7.h"
int main() 
{ // hallo4_impl(); // nicht moeglich 
::hallo4(); ::std::cout << "Peter!\n"; }

::std::cout
Hallo, Peter!

Funktionsschablonen

Wenn eine Schablonenfunktion von anderen Übersetzungseinheiten aus verwendet werden soll, dann darf sie nicht in einem namenlosen Namensraum definiert werden und muß mit dem Schlüsselwort "export" gekennzeichnet werden (nicht zu verwechseln mit dem ähnlich klingenden Schlüsselwort "extern").

maximum1.h
template<typename T> 
extern T maximum( T const a, T const b );

maximum1.cpp
export template<typename T> 
T ::maximum( T const a, T const b ){ return a > b ? a : b; };

maximum1_ec.cpp
#include <iostream> // ::std::cout 
#include <ostream> // <<
#include "maximum1.h" // ::maximum
int main() 
{ ::std::cout << ::maximum<int>( 10, 10 )<< '\n';  
::std::cout << ::maximum( 10, 10 )<< '\n'; }

Es gibt allerdings nur wenige C++ -Implementation. Viele sogenannte „C++ -Compiler“ unterstützen in Wirklichkeit nur einen Teil der Sprache C++, zu dem das Schlüsselwort "export" nicht gehört. Bei solchen Produkten muß die Schablone dann ersatzweise in der Kopfdatei des sie exportierenden Moduls definiert werden.

maximum2.h
template<typename T> 
T maximum( T const a, T const b ){ return a > b ? a : b; };

maximum2_ec.cpp
#include <iostream> // ::std::cout 
#include <ostream> // <<
#include "maximum2.h" // ::maximum
int main() 
{ ::std::cout << ::maximum<int>( 10, 10 )<< '\n';  
::std::cout << ::maximum( 10, 10 )<< '\n'; }

Seiteninformationen und Impressum   |   Mitteilungsformular  |   "ram@zedat.fu-berlin.de" (ohne die Anführungszeichen) ist die Netzpostadresse von Stefan Ram.   |   Eine Verbindung zur Stefan-Ram-Startseite befindet sich oben auf dieser Seite hinter dem Text "Stefan Ram".)  |   Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram. Schlüsselwörter zu dieser Seite/relevant keywords describing this page: Stefan Ram Berlin slrprd slrprd stefanramberlin spellched stefanram721231 stefan_ram:721231 C++ getrennte Compilierung C++ Include-Guard C++ header-File, include-Wächter, source, source code,sourcecode, Programmier sprache C++ Sprache, C++, CXX, C+, Programm, Programme, C++-Programm C++ Sprache C++ Programmiersprache C++ c++-Programme, Standard C++, Programmieren in C++, Programmieren in CXX, Programmieren in CPP, Programmieren in Cplusplus, Die Programmiersprache C++, Die Programmiersprache CXX, Die Programmiersprache CPP, Die Programmiersprache Cplusplus, Die Programmier sprache C++, Die Programmier sprache CXX, Die Programmier sprache CPP, Die Programmier sprache Cplusplus, CXX-Programmierung, C++-Programmierung, CPP-Programmierung, c-plus-plus, cpluplus-Programmierung, ANSI-C++, ANSI-CXX, ANSI-CPP, ANSI C++, ANSI CXX, ANSI-cpluscplus ISO-C++, ISO-CXX, ISO CPP, ISO C++, ISO CXX, ISO/IEC-C++, ISO/IEC-CXX, ISO/IEC CPP, ISO/IEC C++, ISO/IEC CXX, IEC-C++, IEC-CXX, IEC CPP, IEC C++, IEC CXX, International Standard ISO/IEC 14882 First edition 1998-09-01, ISO/IEC 14882:1998(E), ISO/IEC 14882:2003(E), ASC X3, 7/27/98, c plus plus, C ++, cplusplus, c plus plus, Standard C+ programmieren, Stamdard C++ programmieren, Standart C+ programmieren, Stamdart C++ programmieren, INCITS/ISO/IEC 14882-1998, Information Technology - Programming Languages - C++ (formerly ISO/IEC 14882-1998), Programmieren in C++,Programmiersprache C++ CPP CXX Cplusplus c plus plus International Standard ISO/IEC 14882 First edition 1998-09-01, Softwareentwicklung, Software-Entwicklung, Software Entwicklung, Softwareprogrammierung, Software-Programmierung, Software Programmierung, Softwareherstellung, Software-Herstellung, Software Herstellung, Softwareerstellung, Software-Erstellung, Software Erstellung, Softwareengineering, Software-Engineering, Software Engineering, Softwareenginering, Software-Enginering, Software Enginering, Softwaremethodik, Software-Methodik, Software Methodik, Programmiermethodik, Programmier-Methodik, Programmier Methodik, Softwaredidaktik, Software-Didaktik, Software Didaktik, Methodik des Programmierens, Didaktik des Programmierens, Fachdidaktik des Programmierens, Fach-Didaktik des Programmierens, Programmieren, Programmierung, Computer Science, Informatik, Informatik, Informationspädagogik, Informationspaedagogik, Programmierer, programmieren, Quellcode, Quelltext, Quelle, Quellen, Informatiker, Fachinformatiker, Entwickler, mit Stil, mit Stiel, mit Still, , Einführung, Einfuehrung, Einführungen, Einfuehrungen, eLearning-Modul, e-Learning-Modul, eLearning-Module, e-Learning-Module, Kurs Berlin, Kurse Berlin, Kursus, Vortrag, Vorträge, Vortraege, Lehrgang, Lehrgänge, Lehrgaenge, kostenloses Lehrmaterial, kostenlose Lehrmaterialien, Vorlesung, Vorlesungen, Unterrichtseinheit, Unterrichtseinheiten, kostenloses Unterrichtsmaterial im Internet, kostenlose Unterrichtsmaterialien im Internet, Ausbildung, Ausbildungen, für die Ausbildung, Fortbildung, Fortbildungen, Weiterbildung, Weiterbildungen, Schulung Berlin, Schulungen Berlin, Internetschulung, Webschulung, Kursunterlage, Kursunterlagen, trainer Berlin, Didaktik, Informatikunterricht, Primer, Skript FH, Skripte FH, Skriptum FH, Skripts FH, Script FH, Scripte FH, Scriptum FH, Scripts FH, howto, how-to, how to, Lehrbuch, Buch, Bücher, Buecher, Bericht, Crash Kurs Berlin, Crash-Kurs Berlin, Crashkurs Berlin, Report, Sachtext, Sachtexte, Übung, Übungen, Uebung, Uebungen, course, PbclevtugFgrsnaEnz, lecture note, lecture notes, Tutorial, Tutor, Tutorium, Teacher, Lehrer Berlin, Trainer Berlin, Beratung Berlin, Anleitung zum, Anleitungen zum, Einführung, Einfuehrung, Einführungen, Einfuehrungen, Handbuch für, Handbücher, Handbuecher, Support, Diplomarbeit, Facharbeit, Hausarbeit, Hausarbeiten, Werk, Werke, Text, Übungsblatt, Uebungsblatt, Lösung, Loesung, Lösungen, Loesungen, Auflösung, Aufloesung, Auflösungen, Aufloesungen, Facharbeit, Facharbeiten, Forum, Training, manual, Folie, Folien, Lehrmittel, beratung, Definition von, Allgemeine Erklärung, Allgemeine Erklaerung, Allgemeine Erklärungen, Allgemeine Erklaerung, Allgemeine Erklaerungen, Einfache Erklärung einfach, Einfache Erklaerung einfach, Einfache Erklärungen, Einfache Erklaerung, Einfache Erklaerungen, zum Thema, FAQ, FAQs, Konzept, Lernkurs, Lern-Kurs, Lernkurse, Lern-Kurse, eine kurze Erklärung, Begriff, Begriffe, Erklärung zu Begriffen, begriffbestimmung, begriffbestimmung, Begriffsbestimmung, Begriffserklärung, Begriffserklaerung, Wort, Worterklärung, Worterklaerung, Definition, Beispiel, Beispiele, Bedeutung, Bedeutungen, was bedeutet, Begriffsdefinition, für Anfänger, fuer Anfaenger, für Einsteiger, für Beginner, zum selber Lernen, handout, hand out, web based training, WBT, Net Based Training, NBT, computer based training, CBT, virtual learning environment, virtual university, für die Schule, Seminar, Seminare, Vorgehensweise, Pädagogik, Paedagogik, Akademie, Onlineacademie, Onlineakademie, Wissen, Unterrichtsvorbereitung für das Fach, Unterricht, für Lehrer, für Lehrerinnen, Referat, Referate, Hausaufgabe, Hausaufgaben, Tip, Tipp. Tipps und Tricks, Tips und Tricks, Methode, Methoden, Methodik, Funktion, Funktionsweise, Aufbau, Prinzip, Grundlage, Grundlagen, Internetschulung, Unterlage, Unterlagen, Struktur, Frage, Fragen, Antwort, Antworten, Schulunterricht, zum erlernen, was ist das?, wie?, lerne, Onlineausbildung, Onlinelehrgang, Onlinekurs, Onlinebuch, Webbuch, Academy, Fachhochschule, FH, TFH, Hochschule, Universität, Universitaet, Uni, Schule, Berufsschule, Gymnasium, Erste Schritte mit, Dozent, Dozenten, Zusammenfassung, Übersicht, Term, Fachwort, Fachbegriff, Fachbegriffe, Grundbegriff, Grundbegriffe, Lektion, Lektionen, Bedienungsanleitung, Bedienungsanleitungen, Spezialist, Spezialisten, Coaching, Coach, Fachbuch, technologie, Unterschied zwischen, Unterschiede zwischen, lehren, unterrichten, für das Studium, für Studenten, für Studentinnen, für Studierende, für Schüler, für Schülerinnen, Wie kann ich, Wie kann man, Hilfe, selber, erstellen, Erstellung, Beginner, Online-Seminar, Online-Kurs, Online-Schulung, ich, gebrauchsanweisung, gebrauchsanleitung, Bedienungsanweisung, Einweisung, Kurzinfo, Internet-Kurs, Internet-Kurse, Online-Training, Intensiv, Intensivkurs, Vortragsreihe, Präsentation, Grundzüge, Mitschrift, Mitschriften, Verständnis, verstehen, anwenden, Hintergrundwissen, Hintergrund, Hintergründe, content, Funktionsprinzip, Schritt für Schritt; E-Learning; elearning; online learning; Fernlehre, Fernlehrgang, Fernlehrgänge, Referent, Referenten, Fernkurs, Fernkurse, Fernstudium, Fernschule, Fernuniversität, Fernlehrer, Denken, Qualifizierungsmaßnahme, Qualifizierung, Qualifizierungen, Volkshochschulkurs, Volkshochschulkurse, Internet-Learning-Plattform, Online-Learning-Plattform, E-Learning-Plattform, Internetlearning-Plattform, Onlinelearning-Plattform, Elearning-Plattform, jetzt, Kochbuch, einfach erklärt, Kenntnis, Kenntniss, Kenntnisse, deutsche Hilfe, lernen und verstehen; blended learning; courseware, Profi, Profis, professionell, professionelle, professionelles, profesionell, profesionelle, profesionelles, professionel, gekonnt, für Könner, Grundkurs, Leistungskurs, Aufbaukurs, Lehrtext, Lehrtexte, Fachtext, Fachtexte, Ausarbeitung, distance learning, Online Seminar, distance education, Online Tutorium, Online Tutorien, technology-based learning, Computer based learning, CBL, Internet Based learning, IBL, Web based learning, WBL, online-learning, OL, online-training, OT, CAI, Computer Assisted Instruction, CUU, Computerunterstützter Unterricht, Computer-unterstützter Unterricht, Know how, Grundkenntnis, Grundkenntnisse, Kompetenz, Schulungsunterlagen, Insiderwissen, Rat, Lehrerinnen und Lehrer, ABC, Überblick, Arbeitsblatt, Sekundarstufe, Oberstufe, Material, Materialien, Unterrichtsentwurf, Unterrichtsentwürfe, Lerntip, Lerntips, Lerntipp, Lerntipps, ebook, schnell lernen, Lerner, Lernender, Lernende Erwachsenenbildung, Frage und Antwort, Selbststudium, Selbstudium, Umschulung, , kostenlos, kostenlose, kostenloses, kosten los, kosten lose, kosten loses, gratis, free, frei, freie, freies, privat, private, privates, homepage, home-page, home page, website, web site, webpage, web-page, web page, webpages, web-pages, web pages, webseite, Web-Seite, Webseite, Webseiten, Web-Artikel, Web Artikel, online, on-line, on line, download downloaden, down load, or, deutsch, deutsche, deutsches, deutscher, Deutschland, deutschsprachig, deutschsprachige, deutschsprachiges, german, germany, and, uebersicht, Uerbersicht, uebersichten, Uebersichten, Übersicht, übersicht, Übersichten, übersichten, Uebersicht, uebersicht, Uebersichten, uebersichten, Info, Infos zu, Information über, ueber, Informationen über, Auskunft, Auskünfte, Auskuenfte, Dienst, PbclevtugFgrsnaEnz, Angebot, Angebote, Anbieter, server, für, fuer, in, an, keyword, keywords, key word, keywords, internet, internets, net, network, net work, networks, net works, web, www, world wide web, Theorie, Praxis, Anwendung, DV, IT, glossar, fachwörterbuch it-glossar, computer lexikon, Computerlexikon, Computer-Lexikon, Lexikon, computer lexicon, Computerlexicon, Computer-Lexicon, Lexicon, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 was ist ein, was ist das, was sind, definiere, definition, define, Inhalt, html, xhtml, free im netz, PDF Text, digital, digitale, binär, binäre, elektronisch, elektronische, fachbegriff, fachbegriffe, konzept, Begriff, allgemein, allgemeine, allgemeines, Technik, Datentechnik, Digitaltechnik, Binätechnik, online lesen; , Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd721231, slrprddef721231, PbclevtugFgrsnaEnz Erklärung, Beschreibung, Info, Information, Hinweis,

Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram.
https://www.purl.org/stefan_ram/pub/c++_getrennte_uebersetzung_de