2016-08-16 5 views
-2

Verständnis weiß, dass ich das Problem der rekursiven Definition von Typen in C++ für Membervariablen:die „Mutual Rekursion Ausgabe“ für den Rückgabetyp von Funktionen

#include "B.h" 
class A 
{ 
    B b; 
}; 

#include "A.h" 
class B 
{ 
    A b; 
}; 

Der Compiler darüber beschwert, weil Es ist nicht möglich, den Speicher auf diese rekursive Weise zuzuweisen.

Was ich nicht verstehe, ist, dass dies auch zu Funktionsdefinitionen zu gelten scheint:

#include "B.h" 
class A 
{ 
    B foo(); 
}; 

#include "A.h" 
class B 
{ 
    A bar(); 
}; 

Die Compiler gibt den gleichen Fehler:

error: ‘A’ does not name a type 
error: ‘B’ does not name a type 

Warum ist das? Es macht für mich keinen Sinn, dass der Compiler Platz für den Rückgabetyp reservieren muss. Soll ich dieses Problem mit Pointern und Forward-Deklaration lösen? Nach meiner Erfahrung (von Java kommend) ist es ziemlich üblich, dass Programmierer diese rekursiven Definitionen zum Entwerfen von Software verwenden. Es scheint so schwer zu sein, dies in C++ zu realisieren.

+0

Der Yes-Bereich muss für den Rückgabewert reserviert werden. Java gibt alle Klassenobjekte als Referenz zurück. –

+0

Forward-Referenz ist genug, um Ihre Inter-Abhängigkeit zu lösen. – Jarod42

+0

War meine Frage schlecht? Ich frage mich, warum es Downvotes gibt. Vielleicht kann mir jemand Feedback geben und ich kann mich beim nächsten Mal verbessern. Ich würde es schätzen. – aeduG

Antwort

2

Soweit Funktionsdefinitionen gehen, alles was Sie brauchen, ist eine entsprechende Forward-Deklaration:

class A; 
class B; 

class A 
{ 
    B foo(); 
}; 

class B 
{ 
    A bar(); 
}; 

Dies wird ohne Probleme kompilieren. Fühlen Sie sich frei, dies in zwei separate Header-Dateien zu zerlegen, mit einer entsprechenden Forward-Deklaration anstelle einer #include.

Beachten Sie, dass der Grund, warum Sie nicht Klassenmitglieder auf die gleiche Weise deklarieren können, ist, weil dies effektiv eine Klasse enthalten wird. Leider, wenn das möglich wäre, wäre das Endergebnis ein massives schwarzes Loch, das alles Leben verschluckt, wie wir es kennen, und das wollen wir sicher nicht ...

Wie auch immer, der andere Punkt, den Sie kennen Denken Sie daran, dass Sie hier von Ihrem Java-Hintergrund betroffen sind. Klassen arbeiten in C++ grundsätzlich anders als in Java, trotz der täuschend ähnlichen Syntax. Sie sollten besser alles vergessen, was Sie über die Funktionsweise von Klassen in Java wissen. Sonst wirst du immer wieder aus der Bahn geraten. In Java führt eine ähnliche Gruppe von Deklarationen nicht dazu, dass eine Klasse sich selbst enthält, sondern in C++. Dies liegt daran, dass in Java jede Klasseninstanz wirklich ein Zeiger auf eine Klasse ist, aber in C++ ist es die Klasse selbst, in Fleisch und Blut.

In C++, die wirkliche Äquivalent zu dieser Art von einer rekursiven Klassendeklaration wäre:

class A 
{ 
    std::shared_ptr<B> b; 
}; 

class B 
{ 
    std::shared_ptr<B> A; 
}; 

(für den Moment an Erklärungen der erforderlichen ignorieren, die hier gelten, auch).

Und das wird in C++ ebenso gut funktionieren, wie es in Java funktioniert (der std::shared_ptr<> Teil ist das Äquivalent von Java's Objektreferenzzählung, Sortierung). Diese entspricht Ihrem ähnlichen Konstrukt in Java.

2

Sie benötigen eine forward-Deklaration:

class B; // forward declaration 

class A 
{ 
    B foo(); 
}; 

class B 
{ 
    A bar(); 
}; 

Die Erklärung oben weist den Compiler an, die class B vorhanden ist, aber nicht, wie es aussieht. Dies reicht aus, um es als Parameter oder Rückgabetyp einer Funktion oder Methode zu verwenden. Dann können Sie mit der eigentlichen Definition fortfahren.

+0

Vielen Dank für die Antwort. Ich wusste, dass ich es mit Vorwärtsdeklaration lösen kann, war mir aber nicht sicher, ob es der richtige oder der beste Weg war. Wenn Ihr Code in separate Header-Dateien aufgeteilt ist, denke ich, eine andere "Klasse A;" wird in Datei für Klasse B benötigt – aeduG

1

What I don't understand is that this seems to apply to function definitions as well:

Funktionen können durch den Compiler, und der einzige Weg, das zu tun ist inlined, wenn Sie das genaue Layout des Rückgabetypen kennen. Und außerdem muss der Compiler wissen, wie der Rückgabetyp der Funktion


Hinweis zu konstruieren: Der Compiler muss nicht die vollständige Definition des Rückgabetypen einer Funktionsdeklaration wissen, aber Es muss bei der Definition darüber informiert werden.

//file A.h 
class B; //forward declaration 

class A 
{ 
    B foo(); //declaration 
}; 

//file A.cpp 
#include "B.h" 

B A::foo(){ .... } //definition 

//file B.h 
class A; //forward declaration 
class B 
{ 
    A bar(); //declaration, works 
    A moo() { .... } //Declaration + Definition, Fails to see full definition of `A` 
}; 

//file B.cpp 
#include "A.h" 

A B::boo() { ... } 
Verwandte Themen