
Einfachheit
Bei: http://www.learncpp.com/cpp-tutorial/19-header-files/
Folgendes wird erwähnt:
add.cpp:
int add(int x, int y)
{
return x + y;
}
main.cpp:
#include <iostream>
int add(int x, int y); // forward declaration using function prototype
int main()
{
using namespace std;
cout << "The sum of 3 and 4 is " << add(3, 4) << endl;
return 0;
}
Wir haben eine Vorwärtsdeklaration verwendet, damit der Compiler weiß, was “add
” war beim Kompilieren main.cpp
. Wie bereits erwähnt, kann das Schreiben von Forward-Deklarationen für jede Funktion, die Sie verwenden möchten und die sich in einer anderen Datei befindet, schnell mühsam werden.
Können Sie erklären “Vorwärtserklärung” weiter? Was ist das Problem, wenn wir es in der verwenden main()
Funktion?

Scott Langham
Warum die Vorwärtsdeklaration in C++ notwendig ist
Der Compiler möchte sicherstellen, dass Sie keine Rechtschreibfehler gemacht oder die falsche Anzahl von Argumenten an die Funktion übergeben haben. Es besteht also darauf, dass es zuerst eine Deklaration von „add“ (oder anderen Typen, Klassen oder Funktionen) sieht, bevor es verwendet wird.
Dies ermöglicht dem Compiler wirklich nur, den Code besser zu validieren und lose Enden zu beseitigen, sodass er eine ordentlich aussehende Objektdatei erstellen kann. Wenn Sie keine deklarierten Dinge weiterleiten müssten, würde der Compiler eine Objektdatei erzeugen, die Informationen über alle möglichen Vermutungen bezüglich der Funktion enthalten müsste add
könnte sein. Und der Linker müsste eine sehr clevere Logik enthalten, um herauszufinden, welche add
du wolltest eigentlich anrufen, wenn die add
Die Funktion befindet sich möglicherweise in einer anderen Objektdatei, die der Linker mit derjenigen verbindet, die add verwendet, um a zu erzeugen dll
oder exe
. Es ist möglich, dass der Linker einen Fehler macht add
. Sagen Sie, Sie wollten verwenden int add(int a, float b)
aber versehentlich vergessen, es zu schreiben, aber der Linker hat ein bereits vorhandenes gefunden int add(int a, int b)
und dachte, das sei das Richtige und benutzte stattdessen das. Ihr Code würde kompilieren, aber nicht das tun, was Sie erwartet haben.
Um die Dinge explizit zu halten und Vermutungen usw. zu vermeiden, besteht der Compiler darauf, dass Sie alles deklarieren, bevor es verwendet wird.
Unterschied zwischen Deklaration und Definition
Nebenbei ist es wichtig, den Unterschied zwischen einer Deklaration und einer Definition zu kennen. Eine Deklaration liefert gerade genug Code, um zu zeigen, wie etwas aussieht. Für eine Funktion sind dies also der Rückgabetyp, die Aufrufkonvention, der Methodenname, die Argumente und ihre Typen. Der Code für die Methode ist jedoch nicht erforderlich. Für eine Definition braucht man die Deklaration und dann auch noch den Code für die Funktion.
Wie Forward-Deklarationen die Build-Zeiten erheblich verkürzen können
Sie können die Deklaration einer Funktion in Ihren Strom bekommen .cpp
oder .h
Datei, indem Sie den Header #einschließen, der bereits eine Deklaration der Funktion enthält. Dies kann jedoch Ihre Kompilierung verlangsamen, insbesondere wenn Sie #include
eine Überschrift in a .h
anstatt .cpp
Ihres Programms, wie alles, was die #beinhaltet .h
Sie würden am Ende alle Header #include schreiben, für die Sie #includes geschrieben haben. Plötzlich hat der Compiler Seiten und Seiten mit Code eingeschlossen, die er kompilieren muss, selbst wenn Sie nur eine oder zwei Funktionen verwenden wollten. Um dies zu vermeiden, können Sie eine Vorwärtsdeklaration verwenden und die Deklaration der Funktion einfach selbst oben in der Datei eingeben. Wenn Sie nur wenige Funktionen verwenden, kann dies Ihre Kompilierungen wirklich schneller machen im Vergleich zu immer #inklusive des Headers. Bei wirklich großen Projekten kann der Unterschied eine Stunde oder mehr an Kompilierzeit betragen, die auf wenige Minuten reduziert wird.
Brechen Sie zyklische Referenzen auf, wenn sich zwei Definitionen gegenseitig verwenden
Darüber hinaus können Vorwärtsdeklarationen Ihnen helfen, Zyklen zu durchbrechen. Hier versuchen zwei Funktionen, sich gegenseitig zu verwenden. Wenn dies passiert (und es ist eine vollkommen gültige Sache), können Sie #include
eine Header-Datei, aber diese Header-Datei versucht es #include
die Header-Datei, die Sie gerade schreiben … die dann den anderen Header enthält, der den # enthält, den Sie gerade schreiben. Sie stecken in einer Henne-und-Ei-Situation, in der jede Header-Datei versucht, die andere wieder #einzuschließen. Um dies zu lösen, können Sie die benötigten Teile in einer der Dateien vorwärts deklarieren und das #include aus dieser Datei weglassen.
Z.B:
Datei Car.h
#include "Wheel.h" // Include Wheel's definition so it can be used in Car.
#include <vector>
class Car
{
std::vector<Wheel> wheels;
};
Datei Wheel.h
Hmm… die Deklaration von Car
wird hier als benötigt Wheel
hat einen Zeiger auf a Car
aber Car.h
kann hier nicht eingefügt werden, da dies zu einem Compilerfehler führen würde. Wenn Car.h
enthalten war, würde das dann versuchen, aufzunehmen Wheel.h
was beinhalten würde Car.h
was beinhalten würde Wheel.h
und das würde ewig so weitergehen, also löst der Compiler stattdessen einen Fehler aus. Die Lösung ist die Weiterleitungsdeklaration Car
stattdessen:
class Car; // forward declaration
class Wheel
{
Car* car;
};
Wenn Klasse Wheel
hatte Methoden, die Methoden von aufrufen müssen Car
könnten diese Methoden in definiert werden Wheel.cpp
und Wheel.cpp
kann jetzt einschließen Car.h
ohne einen Kreislauf zu verursachen.
Der Compiler sucht nach jedem Symbol, das in der aktuellen Übersetzungseinheit verwendet wird, vorher deklariert wurde oder nicht in der aktuellen Einheit. Es ist nur eine Frage des Stils, alle Methodensignaturen am Anfang einer Quelldatei bereitzustellen, während Definitionen später bereitgestellt werden. Die signifikante Verwendung davon ist, wenn Sie einen Zeiger auf eine Klasse als Mitgliedsvariable einer anderen Klasse verwenden.
//foo.h
class bar; // This is useful
class foo
{
bar* obj; // Pointer or even a reference.
};
// foo.cpp
#include "bar.h"
#include "foo.h"
Verwenden Sie also nach Möglichkeit Vorwärtsdeklarationen in Klassen. Wenn Ihr Programm nur Funktionen hat (mit ho Header-Dateien), dann ist das Bereitstellen von Prototypen am Anfang nur eine Frage des Stils. Dies wäre jedenfalls der Fall gewesen, wenn die Header-Datei in einem normalen Programm mit Header vorhanden gewesen wäre, das nur Funktionen hat.
Da C++ von oben nach unten geparst wird, muss der Compiler über Dinge Bescheid wissen, bevor sie verwendet werden. Wenn Sie also referenzieren:
int add( int x, int y )
in der Hauptfunktion muss der Compiler wissen, dass sie existiert. Um dies zu beweisen, versuchen Sie, es unter die Hauptfunktion zu verschieben, und Sie erhalten einen Compilerfehler.
Also ein ‘Vorwärtserklärung“, steht auf der Dose. Es erklärt etwas im Voraus seiner Verwendung.
Im Allgemeinen würden Sie Vorwärtsdeklarationen in eine Header-Datei aufnehmen und dann diese Header-Datei auf die gleiche Weise einschließen iostream ist enthalten.

sbi
Der Begriff “Vorwärtserklärung” wird in C++ meistens nur für verwendet Klassenerklärungen. Siehe (das Ende von) dieser Antwort, warum eine “Vorwärtsdeklaration” einer Klasse wirklich nur eine einfache ist Klassenerklärung mit ausgefallenem Namen.
Mit anderen Worten, das „Forward“ fügt dem Begriff als nur Ballast hinzu irgendein Die Deklaration kann insofern als vorwärts angesehen werden, als sie einen Bezeichner deklariert Vor es ist benutzt.
(Was ist ein Erklärung im Gegensatz zu a Definitionsiehe nochmal Was ist der Unterschied zwischen einer Definition und einer Deklaration?)
Wenn der Compiler sieht add(3, 4)
es muss wissen, was das bedeutet. Mit der Forward-Deklaration teilen Sie dem Compiler das im Grunde mit add
ist eine Funktion, die zwei Ganzzahlen nimmt und eine Ganzzahl zurückgibt. Dies ist eine wichtige Information für den Compiler, da er 4 und 5 in der richtigen Darstellung auf den Stack legen muss und wissen muss, welchen Typ das von add zurückgegebene Ding ist.
Zu diesem Zeitpunkt kümmert sich der Compiler nicht um die tatsächlich Implementierung von add
dh wo es ist (oder wenn es ist sogar eins) und wenn es kompiliert. Das kommt später in den Blick, nach dem Kompilieren der Quelldateien, wenn der Linker aufgerufen wird.
int add(int x, int y); // forward declaration using function prototype
Können Sie “Forward Declaration” näher erläutern? Was ist das Problem, wenn wir es in der Funktion main() verwenden?
Es ist dasselbe wie #include"add.h"
. Wenn Sie wissen, erweitert der Präprozessor die Datei, die Sie erwähnen #include
in der .cpp-Datei, wo Sie die schreiben #include
Richtlinie. Das heißt, wenn Sie schreiben #include"add.h"
Sie erhalten dasselbe, es ist, als ob Sie eine “Vorwärtsdeklaration” durchführen würden.
Ich gehe davon aus add.h
hat diese Zeile:
int add(int x, int y);

Jack
Eine kurze Ergänzung zu: Normalerweise fügen Sie diese Vorwärtsreferenzen in eine Header-Datei ein, die zur .c (pp) -Datei gehört, in der die Funktion / Variable usw. implementiert ist. in deinem Beispiel würde das so aussehen: add.h:
extern int add(int a, int b);
das Schlüsselwort extern besagt, dass die Funktion eigentlich in einer externen Datei deklariert ist (könnte auch eine Bibliothek etc. sein). Ihre main.c würde so aussehen:
#include
#include "add.h"
int main()
{
.
.
.
10027800cookie-checkWas sind Vorwärtsdeklarationen in C++?yes
Eine “Vorwärtsdeklaration” ist wirklich nur eine Deklaration. Siehe (das Ende) dieser Antwort: stackoverflow.com/questions/1410563/…
– sbi
21. Januar 2011 um 10:33 Uhr