2016-08-16 6 views
-2

Je sais que le problème de la définition récursive des types en C++ pour les variables membres:Comprendre la « mutuelle Recursion question » pour le type de retour Fonctions

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

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

Le compilateur se plaint de ce que il n'est pas possible d'allouer la mémoire de cette manière récursive.

Ce que je ne comprends pas est que cela semble appliquer aux définitions de fonction ainsi:

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

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

Les compilateurs donne la même erreur:

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

Pourquoi est-ce? Cela n'a pas de sens pour moi que le compilateur ait besoin de réserver de l'espace pour le type de retour. Devrais-je résoudre ce problème avec des pointeurs et une déclaration forward? Dans mon expérience (venant de Java), il est assez commun que les programmeurs utilisent ces définitions récursives pour concevoir des logiciels. Cela semble si difficile à réaliser en C++.

+0

Oui, l'espace doit être réservé pour la valeur de retour. Java renvoie tous les objets de classe par référence. –

+0

La référence vers l'avant est suffisante pour résoudre votre interdépendance. – Jarod42

+0

Ma question était-elle mauvaise? Je me demande pourquoi il y a des downvotes. Peut-être que quelqu'un peut me donner des commentaires et je peux m'améliorer la prochaine fois. Je l'apprécierais. – aeduG

Répondre

2

En ce qui concerne les définitions de fonctions vont, tout ce que vous avez besoin est une déclaration appropriée avant:

class A; 
class B; 

class A 
{ 
    B foo(); 
}; 

class B 
{ 
    A bar(); 
}; 

Cela va compiler sans problèmes. N'hésitez pas à couper ceci en deux fichiers d'en-tête séparés, avec une déclaration avant appropriée au lieu d'un #include.

Notez que la raison pour laquelle vous ne pouvez pas déclarer les membres de classe de la même manière est que cette classe contiendra effectivement une classe. Malheureusement, si cela était possible, le résultat final serait un énorme trou noir qui engloutira toute la vie telle que nous la connaissons, et nous ne voulons certainement pas que cela se produise ...

Quoi qu'il en soit, l'autre point Vous devez garder à l'esprit que vous êtes affecté par votre arrière-plan Java. Les classes fonctionnent fondamentalement différentes en C++ qu'elles ne le font en Java, malgré la syntaxe trompeusement similaire. Vous feriez mieux d'oublier tout ce que vous savez sur le fonctionnement des classes en Java. Sinon, vous continuerez à sortir de la piste, comme ça. En Java, un ensemble similaire de déclarations n'aboutit pas à ce que la classe se contienne elle-même, mais en C++. C'est parce que dans Java chaque instance de classe est vraiment un pointeur vers une classe, mais en C++ c'est la classe elle-même, en chair et en os.

En C++, le vrai équivalent à ce genre d'une déclaration de classe récursive serait:

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

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

(ignorant pour le moment les déclarations nécessaires avant applicables ici aussi).

Et cela fonctionnera aussi bien en C++ car il fonctionne en Java (la partie std::shared_ptr<> est l'équivalent du comptage des références d'objet de Java, sorte-de). Cette est ce qui équivaut à votre construction similaire en Java.

2

Vous avez besoin d'une déclaration avant:

class B; // forward declaration 

class A 
{ 
    B foo(); 
}; 

class B 
{ 
    A bar(); 
}; 

La déclaration indique au-dessus du compilateur qui class B existe, mais pas à quoi il ressemble. Cela suffit pour l'utiliser en tant que paramètre ou type de retour d'une fonction ou d'une méthode. Ensuite, vous pouvez suivre avec la définition réelle.

+0

Merci pour la réponse. Je savais que je pouvais le résoudre avec une déclaration avant mais je ne savais pas si c'était la bonne ou la meilleure façon. Si votre code est divisé dans des fichiers d'en-tête séparés, je pense à une autre "classe A"; est nécessaire dans le fichier pour la classe B. – aeduG

1

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

Les fonctions peuvent être inline par le compilateur, et la seule façon de le faire est quand vous connaissez la disposition exacte du type de retour. Et d'ailleurs, le compilateur doit savoir comment construire le type de retour de la fonction


Note: Le compilateur n'a pas besoin de connaître la définition complète du type de retour d'une déclaration de fonction, mais , il a besoin de savoir à ce sujet à la définition.

//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() { ... }