Warum C ++ Vorlagen lassen Sie mich unvollständige Typen (forward-Deklarationen) umgehen?
-
05-07-2019 - |
Frage
Ich habe versucht, drei Iterationen des folgenden einfachen Programm. Dies ist ein stark vereinfachte Versuch, ein Behälter-und-Iterator Paar von Klassen zu schreiben, aber ich lief in Probleme mit unvollständigen Typen (forward-Deklarationen). Ich entdecken, dass dies tatsächlich möglich ist, wenn ich alles templatized - aber nur, wenn ich die Template-Parameter tatsächlich verwendet! (Ich erkannte dies an der
Lösung Die erste erfordert eine Definition von Das zweite Beispiel funktioniert, weil es keine Klasse ist, bis Sie tatsächlich in Ihrem Das dritte Beispiel ist eine Spezialisierung für Und Sie kein container
, da Sie einen Kopiervorgang tun. Wenn Sie den Konstruktor von iter
nach container
Definition definieren würden Sie in Ordnung sein. Also: struct container;
struct iter {
container &c;
int *p;
iter(container &c);
};
struct container {
int x;
int &value() { return x; }
iter begin() { return iter(*this); }
};
iter::iter(container &c) : c(c), p(&c.value()) {}
int main() {
container c;
c.begin();
return 0;
}
main
Funktion instanziiert. Zu diesem Zeitpunkt sind alle Typen definiert. Führen Sie einen der iter
oder container
Vorlagen Definition nach der Haupt bewegen und Sie werden einen Fehler getroffen. int
oder so scheint es. Dies sollte kompilieren, da die Template-Parameter für iter
nicht verwendet wird. Sie haben die Spezialisierung Syntax ein wenig abseits stand. Allerdings gibt es keinen richtigen Konstruktor, so dass Sie nur Müll für x
bekommen. Darüber hinaus sind Iteratoren modelliert und durch Zeiger. this
Wert Passing wird nicht viel helfen. Iteratoren werden typischerweise für eine Sequenz erforderlich und nicht ein einzelnes Objekt. Obwohl, es gibt nichts, was man von dem Bau einer stoppen kann. ;
nach einem Funktionskörper benötigen.
Andere Tipps
Sie können dies durch, ohne Vorlagen tun definieren iter :: iter () nach Definition des Behältnisses:
struct container;
struct iter {
container &c;
int *p;
iter(container &c);
};
struct container {
int x;
int &value() { return x; }
iter begin() { return iter(*this); }
};
iter::iter(container &c)
: c(c), p(&c.value()) {}
int main() {
container c;
c.begin();
return 0;
}
Template-Version funktioniert, weil, wenn Sie Vorlagen beiden Klassen instanziiert werden vollständig definiert ist.
Im ersten Fall, Sie versuchen, eine Memberfunktion der Container-Klasse zuzugreifen, bevor die Klasse definiert wurde, so wird dies nicht funktionieren.
Im zweiten Fall wird die Vorlage zum ersten Mal instanziiert es mit einem bestimmten Typ verwendet wird. An diesem Punkt hat sich die Container-Klasse definiert wurde, in Haupt- und so kompiliert.
Im dritten Fall gibt es eine zirkuläre Referenz. Container verwendet iter und iter verwendet Behälter, so kann es nicht funktionieren.