Question sans doute posée mille fois !!!

Le
WebShaker
J'ai un petit problème que je n'arrive pas a résoudre.

j'ai une class A qui contient un tableau de d'objet de la classe B.

D'un autre coté j'aimerai pouvoir stocker un pointeur de la class A dans
l'objet B !!!

mais je ne peux pas inclure classA.h dans la définition de l'objet B
et inclure classB.h dans la définition de l'objet A

car évidement, l'un des deux fichiers est forcément parsé en premier !!!

Comment solutionne t-on ce problème?

Merci
Etienne
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
JKB
Le #23121451
Le Sun, 13 Feb 2011 10:29:59 +0100,
WebShaker
J'ai un petit problème que je n'arrive pas a résoudre.

j'ai une class A qui contient un tableau de d'objet de la classe B.

D'un autre coté j'aimerai pouvoir stocker un pointeur de la class A dans
l'objet B !!!

mais je ne peux pas inclure classA.h dans la définition de l'objet B
et inclure classB.h dans la définition de l'objet A

car évidement, l'un des deux fichiers est forcément parsé en premier !!!

Comment solutionne t-on ce problème?



Bonjour,

Si j'ai bien compris le problème, avec quelque chose du genre :

#ifdef _INCLUDE1_HPP_
# define _INCLUDE1_HPP_

// include_1.hpp
#endif

dans le fichier d'en-tête.

JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Alain Ketterlin
Le #23121441
WebShaker
j'ai une class A qui contient un tableau de d'objet de la classe B.

D'un autre coté j'aimerai pouvoir stocker un pointeur de la class A
dans l'objet B !!!



----- B.hpp ----
class A;
class B {

A * a; ...

};
----- A.hpp ----
#include "B.hpp"
class A {

B bs[...]; ...

};
----------------

Plus les gardes #ifndef/... habituelles.

-- Alain.
Etienne Rousee
Le #23121531
Le 13/02/2011 10:29, WebShaker a écrit :
j'ai une class A qui contient un tableau de d'objet de la classe B.

D'un autre coté j'aimerai pouvoir stocker un pointeur de la class A dans
l'objet B !!!

mais je ne peux pas inclure classA.h dans la définition de l'objet B
et inclure classB.h dans la définition de l'objet A

car évidement, l'un des deux fichiers est forcément parsé en premier !!!

Comment solutionne t-on ce problème?



Dans classA.h :

class A; // prototypes de classes
class B;

classA
{
...........
B _tabB[10]; // par exemple, ou: B *_tabB;
};

Dans classB.h :

class A; // prototypes de classes
class B;

classB
{
...........
A *_ptrA;
};

Et il faut inclure classB.h avant classA.h.

Mais, plutôt qu'un tableau de B, je mettrais
un vector de B* dans la classe A:
std::vector<B *> _vecB;
Comme ça l'ordre des inclusions serait indifférent.

--

Etienne
Mickaël Wolff
Le #23122661
Tout d'abord, le sujet n'est absoluement pas en charte. Il faut un
titre plus explicite.

On 13/02/11 09:51, Etienne Rousee wrote:
Dans classA.h :

class A; // prototypes de classes


En réalité, c'est une déclaration.
Au fait, on appelle cette technique « forwarding declaration ».

Dans classB.h :

class A; // prototypes de classes
class B;


Déclarer class B est inutile ici.

classB
{
...........
A *_ptrA;


Les noms de symboles commençant par un underscore sont réservés aux
implémenteurs de la STL. Le comportement ici est donc indéfini.


Et il faut inclure classB.h avant classA.h.


Pourquoi ? Il faut inclure le moins de fichiers possible dans les
en-têtes, pour limiter le couplage. À moins que tu ne parlais de
l'inclusion des en-têtes dans le module de définition de la class B ?

Mais, plutôt qu'un tableau de B, je mettrais
un vector de B* dans la classe A:
std::vector<B *> _vecB;
Comme ça l'ordre des inclusions serait indifférent.


Au delà de l'ordre des includes, c'est surtout qu'un std::vector sera
plus naturel en C++ qu'un tableau à la C.
Michael Doubez
Le #23123021
On 13 fév, 18:11, Mickaël Wolff
   Tout d'abord, le sujet n'est absoluement pas en charte. Il faut un
titre plus explicite.

On 13/02/11 09:51, Etienne Rousee wrote:> Dans classA.h :

> class A; // prototypes de classes

   En r alit , c'est une d claration.
   Au fait, on appelle cette technique forwarding declaration .

> Dans classB.h :

> class A; // prototypes de classes
> class B;

   D clarer class B est inutile ici.

> classB
> {
> ...........
> A *_ptrA;

   Les noms de symboles commen ant par un underscore sont r serv s au x
impl menteurs de la STL. Le comportement ici est donc ind fini.



Uniquement dans le namespace global.

Les noms réservés dans tous les namespaces sont ceux commençant par u n
underscore ouis une majuscule ou les noms ayant un double underscore.

[snip]

--
Michael
Mickaël Wolff
Le #23123101
On 13/02/11 18:43, Michael Doubez wrote:

Uniquement dans le namespace global.

Les noms réservés dans tous les namespaces sont ceux commençant par un
underscore ouis une majuscule ou les noms ayant un double underscore.



Merci pour la précision. J'avais banni l'usage du leading underscore
depuis que j'avais appris que c'était réservé dans certains cas. Ceci
dit, ça m'explique pourquoi ils utilisent _M_.* dans la STL fournie avec
GCC.

Ceci dit, je pense que c'est quand même une bonne idée de ne pas
utiliser tout les symboles commençant par underscore. Vu que c'est
réservé dans une portée suppérieure, on peut éventuellement avoir des
problèmes de symbole caché.
Etienne Rousee
Le #23123161
Le 13/02/2011 18:11, Mickaël Wolff a écrit :
> Tout d'abord, le sujet n'est absoluement pas en charte. Il faut un
> titre plus explicite.


Oui, j'ai gardé le titre de l'OP, comme toi.

> On 13/02/11 09:51, Etienne Rousee wrote:
>> Dans classA.h :
>>
>> class A; // prototypes de classes


> En réalité, c'est une déclaration.
> Au fait, on appelle cette technique « forwarding declaration ».



Et en français ? Dans l'esprit, c'est prévenir le compilateur que ce
nom existe et que c'est un nom de classe.

>> Dans classB.h :
>>
>> class A; // prototypes de classes
>> class B;


> Déclarer class B est inutile ici.
>
>> classB
>> {
>> ...........
>> A *_ptrA;


> Les noms de symboles commençant par un underscore sont réservés aux
> implémenteurs de la STL. Le comportement ici est donc indéfini.


Il n'y a pas de loi là dessus. C'est juste une question de convention
d'écriture. Il se trouve que j'ai appris le C++ avec cette convention,
mais il y en a d'autres. Il doit même y en avoir une par entreprise
ou presque.

>
>> Et il faut inclure classB.h avant classA.h.


> Pourquoi ? Il faut inclure le moins de fichiers possible dans les
> en-têtes, pour limiter le couplage. À moins que tu ne parlais de
> l'inclusion des en-têtes dans le module de définition de la class B ?


Ici, c'est forcément couplé, puisque l'OP veut se servir de A dans B
et de B dans A. Mais effectivement, je parlais de l'inclusion dans
classB.cpp.

>> Mais, plutôt qu'un tableau de B, je mettrais
>> un vector de B* dans la classe A:
>> std::vector<B *> _vecB;
>> Comme ça l'ordre des inclusions serait indifférent.


> Au delà de l'ordre des includes, c'est surtout qu'un std::vector sera
> plus naturel en C++ qu'un tableau à la C.


Oui pour le vecteur, mais B* au lieu de B influe sur l'ordre.

-- Etienne
Michael Doubez
Le #23123561
On 13 fév, 20:11, Mickaël Wolff
On 13/02/11 18:43, Michael Doubez wrote:

> Uniquement dans le namespace global.

> Les noms r serv s dans tous les namespaces sont ceux commen ant par un
> underscore ouis une majuscule ou les noms ayant un double underscore.

   Merci pour la pr cision. J'avais banni l'usage du leading undersco re
depuis que j'avais appris que c' tait r serv dans certains cas. Ceci
dit, a m'explique pourquoi ils utilisent _M_.* dans la STL fournie avec
GCC.



Il me semble qu'il y a des cas où ça pourrait poser problème avec le
C99 qui réserve plus de noms; je suppose que c'est dû à l'absence de
namespace. Je crois que POSIX ajoute aussi sont lot de formes
réservées.

En pratique, j'ai jamais vu ni entendu parler de problèmes lié à ça .
Et c'est à mon avis une réserve pour pouvoir ajouter des noms
réservés. Et si quelqu'un râle, qu'on puisse lui dire qu'il n'avait
qu'à ne pas utiliser une forme réservée.


   Ceci dit, je pense que c'est quand m me une bonne id e de ne pas
utiliser tout les symboles commen ant par underscore. Vu que c'est
r serv dans une port e supp rieure, on peut ventuellement avoir des
probl mes de symbole cach .



Dans le contexte d'une fonction membre, je ne vois pas de cas
problème. Peut être dans un cas de classe template où un two-phase
lookup aurait dû être utiliser (i.e. utiliser this->_member) et que la
variable globale est utilisé en lieu et place de la variable membre.
C'est un risque assez vague.

AMA c'est plutôt une question de lisibilité. J'ai utilisé un temps la
notation membre_; mais c'est vraiment laid (membre_->foo() ) et pas
très lisible. J'ai vu certains utiliser m_member , mMember ou
myMember. Le dernière forme étant peut être la plus explicite mais à
un je ne sais quoi qui me déplait (peut être mon orgueil qui refuse
d'utiliser des conventions d'amateur même si des gens aussi
expérimentés que James Kanze l'utilisent :)

Au travaille, nous utilisons tous la forme _member. Et je pense que je
ne m'avance pas trop en disant que c'est la forme la plus populaire.

En fait, pour être tout à fait sûr il faudrait que le langage c++
standardise des namespaces de contexte comme dans certains langages
dynamiques:
- m::* pour désigner les noms membres
- g::* les globales
- a::* pour les arguments de fonction

Comme ça je pourrais écrite

int foo;

class MyClass
{
int foo;
}

void
myClass::myClass(int foo, double bar)
{
m::foo = a::foo;
if( g::foo < m::foo )
{

}
}

Je pense que se réserver des namespaces d'une seule lettre ne
casserait pas beaucoup de code. Et ça serait optionnel.

--
Michael
Publicité
Poster une réponse
Anonyme