2010-11-29 4 views
2

je rencontre un problème comme celui-ci: MISE À JOURdéfinition récursive du RPC

class A 
{ 
public: 
    A(){} 
    int i; 
    B b; 
}; 

class B 
{ 
public: 
    B(){} 
    int j; 
    A a; 
}; 

Quand je définis dans un fichier .h, cela donnerait une erreur. Je pense que le problème est la définition récursive. Mais quelqu'un pourrait-il m'aider à résoudre ce problème?

  1. error C2146: syntax error : missing ';' before identifier 'b' c:\users\xingyo\documents\visual studio 2010\projects\cppalgo\recudef\test1.h 9 1 RecuDef

  2. error C4430: missing type specifier - int assumed. Note: C++ does not support default-int c:\users\xingyo\documents\visual studio 2010\projects\cppalgo\recudef\test1.h 9 1 RecuDef

  3. error C4430: missing type specifier - int assumed. Note: C++ does not support default-int c:\users\xingyo\documents\visual studio 2010\projects\cppalgo\recudef\test1.h 9 1 RecuDef

+6

Que voulez-vous exactement faire? L'exemple que vous donnez contient des erreurs et nous laisse deviner. Aviez-vous vraiment l'intention de déclarer une classe imbriquée 'class B' dans la classe' A', etc.? Ce ne serait pas récursif.De plus, si vous obtenez une erreur **, dites-nous quelle est cette erreur **. La première étape pour résoudre une erreur consiste à connaître l'erreur. – sth

+0

Je suis désolé, j'ai mis à jour la question –

Répondre

10

Ce n'est pas possible in extenso en C++. L'explication est que le compilateur a besoin d'une déclaration complète d'une classe pour pouvoir l'utiliser en tant que membre d'une autre classe. Il a simplement besoin de la taille d'un objet de classe.

La solution de contournement en C++ (et en C) consiste à utiliser un pointeur ou une référence en tant que membre d'une des classes. De cette façon, vous pouvez utiliser avant la déclaration comme suit:

class A; // forward declaration 

class B { 
    // ... 
    A* pa; 
}; 

class A { // full declaration 
    // ... 
    B b; 
}; 

C'est votre (et non le compilateur ou l'exécution) la responsabilité de garder l'instance de A cette instance de B des points (ou références) valides.

+0

S'il vous plaît être décent et dire pourquoi vous downvote. –

4

Vous ne pouvez pas le résoudre. C'est sans signification. Vous avez défini A pour contenir B qui contient un autre A qui contient un autre B qui ... Vous ne pouvez pas l'avoir voulu. Peut-être que vous avez besoin d'utiliser un pointeur ou une référence?

+0

Ce ne sont pas des déclarations d'instance, il n'y a pas de récursion ici. –

+0

Ils ne l'étaient pas mais l'édition de l'OP le fait. – EJP

+0

Ce n'est pas seulement insignifiant, c'est physiquement impossible. Si ce que l'OP voulait compiler, cela créerait une structure de données de taille infinie. ;) – Mephane

0

S'il s'agit d'un problème récursif. Déclarez les classes sans les définitions:

class A; 
class B; 

class A 
{ 
    ... 
}; 

class B 
{ 
    ... 
}; 

Voir: http://www.gotw.ca/gotw/034.htm

+1

Les déclarations forward ne fonctionnent que pour les pointeurs et les références. – Dima

+0

@Dima ce n'est pas correct. Ils travaillent également pour les classes, les structures et les espaces de noms, et probablement aussi pour les syndicats. – EJP

+1

@Dima: Il devra utiliser un pointeur ou une référence de toute façon, il est simplement physiquement impossible d'avoir deux classes ou structures qui se contiendront, car le résultat aurait une taille infinie. – Mephane

0

Split, vous codes dans 4 fichiers, disent A.h, A.cpp, B.h et B.cpp.

// A.h 

class B; 
class A { 
public: 
    A(); 
    B* b; 
}; 

// A.cpp 

#include "A.h" 
#include "B.h" 

A::A() : b(new B) { 
} 

// B.h 

class A; 
class B { 
public: 
    B(A* a_); 
    A* a; 
}; 

// B.cpp 

#include "B.h" 
#include "A.h" 

B::B(A* a_) : a(a_) { 
} 

et de les utiliser de cette façon:

#include "A.h" 
#include "B.h" 

int main() { 
    A a; 
    B b(&a); 

    // do logics 

    return 0; 
} 
+1

Les gardes d'en-tête sont manquants. –

+0

Je le savais. Merci quand même. – upriser

0

Vous ne pouvez pas avoir une définition récursive comme celle de C++. Avant de pouvoir déclarer un objet de , A doit être entièrement défini, de sorte que le sizeof(A) soit connu du compilateur. Même chose avec B. Cependant, vous pouvez le contourner en utilisant des pointeurs. Vous pouvez déclarer un pointeur vers un objet de class A simplement en "promettant" pour définir class A ultérieurement. Ceci est appelé déclaration avant.

class B; // forward declaration 

class A 
{ 
    B *b; 
}; 

class B 
{ 
    A *a; 
}; 

Les déclarations anticipées fonctionnent également pour les références.