Ich habe gesehen, dass es in C ++ verschiedene Paradigmen gibt, was in die Header-Datei und was in die CPP-Datei geht. AFAIK, die meisten Leute, besonders die mit C-Hintergrund, machen:
foo.h
class foo {
private:
int mem;
int bar();
public:
foo();
foo(const foo&);
foo& operator=(foo);
~foo();
}
foo.cpp
#include foo.h
foo::bar() { return mem; }
foo::foo() { mem = 42; }
foo::foo(const foo& f) { mem = f.mem; }
foo::operator=(foo f) { mem = f.mem; }
foo::~foo() {}
int main(int argc, char *argv[]) { foo f; }
In der Regel unterrichten meine Dozenten Anfängern wie folgt C ++:
foo.h
class foo {
private:
int mem;
int bar() { return mem; }
public:
foo() { mem = 42; }
foo(const foo& f) { mem = f.mem; }
foo& operator=(foo f) { mem = f.mem; }
~foo() {}
}
foo.cpp
#include foo.h
int main(int argc, char* argv[]) { foo f; }
// other global helper functions, DLL exports, and whatnot
Ursprünglich aus Java stammend, habe ich mich aus mehreren Gründen immer an diesen zweiten Weg gehalten, zum Beispiel, dass ich nur an einer Stelle etwas ändern muss, wenn sich die Schnittstellen- oder Methodennamen ändern, dass ich die unterschiedlichen Einrückungen von Dingen in Klassen mag, wenn ich Blick auf ihre Umsetzung, und das finde ich Namen besser lesbar als im foo
Vergleich zu foo::foo
.
Ich möchte Vor- und Nachteile für beide Arten sammeln. Vielleicht gibt es noch andere Möglichkeiten?
Ein Nachteil meines Weges ist natürlich die Notwendigkeit gelegentlicher Vorwärtserklärungen.
quelle
foo.cpp
Jetzt hat nichts mit deinerfoo
Klasse zu tun und sollte leer gelassen werden (vielleicht aber#include
um dein Build-System glücklich zu machen).Antworten:
Während die zweite Version einfacher zu schreiben ist, vermischt sie Schnittstelle mit Implementierung.
Quelldateien, die Headerdateien enthalten, müssen bei jeder Änderung der Headerdateien neu kompiliert werden. In der ersten Version würden Sie die Header-Datei nur ändern, wenn Sie die Benutzeroberfläche ändern müssen. In der zweiten Version würden Sie die Header-Datei ändern, wenn Sie die Schnittstelle oder die Implementierung ändern müssen.
Außerdem sollten Sie die Implementierungsdetails nicht offenlegen , da Sie mit der zweiten Version keine unnötige Neukompilierung erhalten .
quelle
Ich habe es den zweiten Weg zurück in '93 -95 gemacht. Es dauerte ein paar Minuten, um eine kleine App mit 5-10 Funktionen / Dateien neu zu kompilieren (auf demselben 486 PC ... und nein, ich wusste auch nichts über Klassen, ich war erst 14-15 Jahre alt und es gab kein Internet ) .
Was Sie Anfängern beibringen und was Sie beruflich anwenden, sind also ganz andere Techniken, insbesondere in C ++.
Ich denke, der Vergleich zwischen C ++ und einem F1-Auto ist passend. Sie setzen keine Anfänger in ein F1-Auto (das nicht einmal anspringt, wenn Sie den Motor nicht auf 80-95 Grad Celsius vorheizen).
Unterrichten Sie C ++ nicht als erste Sprache. Sie sollten genug Erfahrung haben, um zu wissen, warum Option 2 schlechter ist als Option 1 im Allgemeinen, ein bisschen zu wissen, was statisches Kompilieren / Verknüpfen bedeutet, und um zu verstehen, warum C ++ es auf die erste Art bevorzugt.
quelle
Die zweite Methode würde ich eine vollständig inline Klasse nennen. Sie schreiben eine Klassendefinition, aber der gesamte Code, der diese verwendet, fügt den Code nur ein.
Ja, der Compiler entscheidet, wann und wann nicht ... In diesem Fall helfen Sie dem Compiler, eine Entscheidung zu treffen, und Sie werden möglicherweise weniger Code generieren und möglicherweise sogar schneller.
Dieser Vorteil wird wahrscheinlich die Tatsache aufwiegen, dass Sie, wenn Sie die Implementierung einer Funktion ändern, die gesamte Quelle, die sie verwendet, neu erstellen müssen. Aufgrund der Leichtigkeit der Klasse werden Sie die Implementierung nicht ändern. Wenn Sie eine neue Methode hinzufügen, müssten Sie den Header trotzdem ändern.
Wenn Ihre Klasse jedoch komplexer wird und sogar eine Schleife hinzufügt, verringert sich der Vorteil dieser Vorgehensweise.
Es hat immer noch seine Vorteile, insbesondere:
Die Kehrseite des Inlinings wird zu einem Problem, wenn Sie Implementierungsspezifikationen in Ihre Kopfzeile einfügen müssen, dh wenn Sie zusätzliche Kopfzeilen einfügen müssen.
Beachten Sie, dass Vorlagen ein Sonderfall sind, da Sie die Implementierungsdetails ziemlich genau angeben müssen. Sie könnten es in einer anderen Datei verdecken, aber es muss dort sein. (Es gibt eine Ausnahme von dieser Regel bei Instanziierungen, aber im Allgemeinen fügen Sie Ihre Vorlagen ein).
quelle
Es kann unwichtig oder wahr sein, wenn Ihre ausführbare Datei größer wird, aber mehr Code in Header-Dateien ermöglicht es dem Compiler, die Geschwindigkeit zu optimieren.
Wenn Sie entscheiden, ob Sie eine reine Header-Bibliothek schreiben möchten , ist dieses Thema nur eines Ihrer Anliegen.
quelle