Ich schreibe dies als separate Antwort und nicht nur als Kommentar, da ich der Antwort von Luc Touraille nicht zustimme, nicht aus Gründen der Legalität, sondern wegen robuster Software und der Gefahr von Fehlinterpretationen.
Insbesondere habe ich ein Problem mit dem impliziten Vertrag darüber, was Benutzer Ihrer Benutzeroberfläche wissen müssen.
Wenn Sie Referenztypen zurückgeben oder akzeptieren, sagen Sie nur, dass sie einen Zeiger oder eine Referenz passieren können, die sie möglicherweise nur durch eine Vorwärtsdeklaration kennen.
Wenn Sie einen unvollständigen Typen kehren X f2();
dann Anrufer sagen Sie müssen die vollständige Typangabe von X haben Sie brauchen es , um das LHS oder temporäres Objekt an der Aufrufstelle zu erstellen.
Wenn Sie einen unvollständigen Typ akzeptieren, muss der Aufrufer das Objekt erstellt haben, das der Parameter ist. Selbst wenn dieses Objekt als ein anderer unvollständiger Typ von einer Funktion zurückgegeben wurde, benötigt die Aufrufsite die vollständige Deklaration. dh:
class X; // forward for two legal declarations
X returnsX();
void XAcceptor(X);
XAcepptor( returnsX() ); // X declaration needs to be known here
Ich denke, es gibt ein wichtiges Prinzip, dass ein Header genügend Informationen liefern sollte, um sie zu verwenden, ohne dass eine Abhängigkeit andere Header erfordert. Das bedeutet, dass der Header in eine Kompilierungseinheit aufgenommen werden kann, ohne einen Compilerfehler zu verursachen, wenn Sie deklarierte Funktionen verwenden.
Außer
Wenn diese externe Abhängigkeit gewünschtes Verhalten ist. Statt bedingte Kompilierung verwenden könnten Sie eine haben gut dokumentierte Anforderung für sie , ihre eigenen Header erklärt X. Diese liefern eine Alternative zu #ifdefs mit und kann eine nützliche Art und Weise sein Mocks oder andere Varianten vorstellen.
Der wichtige Unterschied sind einige Vorlagentechniken, bei denen ausdrücklich nicht erwartet wird, dass Sie sie instanziieren. Sie werden nur erwähnt, damit jemand nicht mit mir bissig wird.