2008-11-21 16 views
7

Je suis en train de déclarer et utiliser une classe B à l'intérieur d'une classe A et définir B en dehors A.
Je sais pertinemment que cela est possible parce que Bjarne Stroustrup
utilise en son livre "Le langage de programmation C++"
(page 293, par exemple les classes String et Srep).classes C++ emboîtés erreur de déclaration avant

Donc ceci est mon morceau minimum de code qui provoque des problèmes

class A{ 
struct B; // forward declaration 
B* c; 
A() { c->i; } 
}; 

struct A::B { 
/* 
* we define struct B like this becuase it 
* was first declared in the namespace A 
*/ 
int i; 
}; 

int main() { 
} 

Ce code donne les erreurs de compilation suivantes en g ++:

tst.cpp: In constructor ‘A::A()’: 
tst.cpp:5: error: invalid use of undefined type ‘struct A::B’ 
tst.cpp:3: error: forward declaration of ‘struct A::B’ 

j'ai essayé de regarder le C++ Faq et closeset J'ai eu était here et here mais
ceux qui ne s'appliquent pas à ma situation. J'ai aussi read this d'ici mais ça ne résout pas mon problème.

gcc et MSVC 2005 donner des erreurs du compilateur sur ce

Répondre

11

Définir le constructeur A après la définition de struct B.

+0

oui, cela a fonctionné merci :) – xxxxxxx

+0

De rien! :-) –

+1

Le constructeur est défini après la déclaration de B. Il doit être défini après que B est défini. –

15

L'expression c->i déréférence le pointeur struct A::B donc une définition complète doit être visible à ce stade dans le programme.

La solution la plus simple consiste à rendre non-inline le constructeur de A et de lui fournir un corps après la définition de struct A::B.

+0

Ou, définissez la fonction comme en ligne en utilisant le mot-clé 'inline' après la définition de la structure B. – Phlucious

7

Ceci est un bon exemple des raisons pour lesquelles vous voulez garder des définitions distinctes des déclarations. Vous devez changer l'ordre des choses pour que le constructeur A::A() soit défini après la définition de struct A::B.

class A 
{ 
    struct B; 
    B* c; 
    A(); 
}; 

struct A::B 
{ 
    int i; 
}; 

A::A() { c->i; } 

int main() 
{ 
    return 0; 
}
1

Fait intéressant, je suis tombé sur le même problème avec la page 293 ('11 .12 classe String) mentionné dans le livre Stroustrup.

L'exemple fourni dans le livre imprimé semble être en faute, en fournissant les méthodes suivantes en ligne, au lieu de les définir après la définition de struct SREP

class String { 
    // ... 
    void check(int i) const { if (i<0 || rep->sz <=i) throw Range(); } 
    char read(int i) const { return rep->s[i]; } 
    void write(int i, char c) { rep=rep->get_own_copy(); rep->s[i]=c; } 
    ...etc... 

Je googlé un peu et trouvé l'auteur dernière mise en œuvre de cette classe de chaînes, disponible ici: http://www2.research.att.com/~bs/string_example.c

Il semble l'avoir modifié de sorte que ces méthodes ne sont plus en ligne, pour éviter le problème mentionné dans ce fil.