classes interdépendantes : déclarer une classe sans la définir
21 réponses
meow
J'ai deux classes, A et B, chacune d=E9pend de sous parties de
l'autre... et j'aimerai si possible =E9viter de multiplier mes arguments
templates. Y a t'il un moyen d'=E9crire quelque chose du genre :
class A; //! t'inqui=E8tes pas copain compilo, la d=E9finition vient plus
loin
class B{
// j'utilise des types d=E9finis dans A
};
class A { // tu vois j'ai pas menti !
// j'utilise des types d=E9finis dans B
}
Bon, ok, =E7a a pas l'air bien joli niveau design... Alors si en sus
vous aviez des conseils pour =E9viter ce genre d'horreur. Je vous
explique un peu mieux mon probl=E8me, histoire de pas parler dans le
vide :
Ma classe A est une structure de donn=E9e qui rend compte d'un objet
volumique (une triangulation 3D, donc un ensemble de tetraedres,
triangles, arretes et sommets avec les relations d'incidences qui vont
bien)
Ma classe B est une structure de donn=E9e qui rend compte d'un objet
surfacique (demi arete, pour qui connait (merci Mr Kettner) )
j'ai un objet a de type A et je veux construire son bord sous la forme
d'un objet b de type B. Pour cette construction, je vais avoir besoin
de stocker les "=E9chafaudages" de b dans a. Donc A doit connaitre B (ou
du moins certaines sous parties de A doivent connaitre certaines sous
parties de B)
Mais je veux aussi que les sommets de b gardent l'information de leur
origine dans a (grosso modo je veux que les sommets de b pointent sur
les sommets de a dont ils sont issus)... moralit=E9 B doit aussi
connaitre A.
.=2E.Je fais comment ? :D
Ce a quoi j'avais pens=E9 partant de l'observation qu'il =E9tait tr=E8s laid
d'avoir un objet qui contienne les "=E9chafaudages" d'un autre, c'=E9tait
d'avoir deux classes tr=E8s proches : A et AA, la premi=E8re vierge de
toute pernition de B, et la seconde qui ne serait utilis=E9e que le
temps de la construction d'un objet de type B. A ne "connaitrait"
ainsi personne, B connaitrait A et AA connaitrait =E0 la fois A et B.
Un objet aa de type AA serait initialis=E9e par copie d'un objet de
classe A dont elle stockerait les r=E9f=E9rences dont on a besoin dans les
=E9l=E9ments de la classe B, et stockerait les "=E9chafaudages" de b avant
d'etre d=E9truit, une fois b construit.
Je pense que ce qui m'a rebut=E9 c'est le fait que ma classe A est tr=E8s
grosse et que =E7a me g=E8ne de "gaspiller" de la place m=E9moire avec deux
objets quasi identiques en m=E9moire.
class A; //! t'inquiètes pas copain compilo, la définition vient plusloin class B{ // j'utilise des types définis dans A }; class A { // tu vois j'ai pas menti ! // j'utilise des types définis dans B }
Bon, ok, ça a pas l'air bien joli niveau design... Alors si en sus vous aviez des conseils pour éviter ce genre d'horreur. Je vous explique un peu mieux mon problème, histoire de pas parler dans le vide :
Je pense que c'est la manière traditionnelle de faire. Aussi laide soit-elle.
class A; //! t'inquiètes pas copain compilo, la définition vient
plusloin
class B{
// j'utilise des types définis dans A
};
class A { // tu vois j'ai pas menti !
// j'utilise des types définis dans B
}
Bon, ok, ça a pas l'air bien joli niveau design... Alors si en sus
vous aviez des conseils pour éviter ce genre d'horreur. Je vous
explique un peu mieux mon problème, histoire de pas parler dans le
vide :
Je pense que c'est la manière traditionnelle de faire. Aussi laide
soit-elle.
class A; //! t'inquiètes pas copain compilo, la définition vient plusloin class B{ // j'utilise des types définis dans A }; class A { // tu vois j'ai pas menti ! // j'utilise des types définis dans B }
Bon, ok, ça a pas l'air bien joli niveau design... Alors si en sus vous aviez des conseils pour éviter ce genre d'horreur. Je vous explique un peu mieux mon problème, histoire de pas parler dans le vide :
Je pense que c'est la manière traditionnelle de faire. Aussi laide soit-elle.
Sylvain
meow wrote on 29/06/2007 17:39:
J'ai deux classes, A et B, chacune dépend de sous parties de l'autre... et j'aimerai si possible éviter de multiplier mes arguments templates. Y a t'il un moyen d'écrire quelque chose du genre :
class A; class B{ // j'utilise des types définis dans A ^^^^^ plus sûrement des méthodes / propriétés.
}; class A { // tu vois j'ai pas menti ! // j'utilise des types définis dans B ^^^^^ idem
}
Bon, ok, ça a pas l'air bien joli niveau design... Alors si en sus vous aviez des conseils pour éviter ce genre d'horreur.
une déclaration avec définition différée n'a rien de très laid; si de plus les classes si définies conjointement, la relecture n'est pas gênée par cela.
[...] Je pense que ce qui m'a rebuté c'est le fait que ma classe A est très grosse et que ça me gène de "gaspiller" de la place mémoire avec deux objets quasi identiques en mémoire.
une alternative à votre approche en, est effet, de ne déclarer qu'une seule et unique classe qui contienne toutes les informations nécessaires à la construction des 2 ensembles de données avec 2 jeux de méthodes d'utilisation selon le besoin externe; on pourrait pour faciliter cet usage définir 2 classes de "travail pur", entièrement initialisée à partir de la première et non à même de générer elle même les points / grandeurs caractéristiques (pour ne pas dupliquer cette partie qui est le corps de votre interdépendance actuelle).
Sylvain.
meow wrote on 29/06/2007 17:39:
J'ai deux classes, A et B, chacune dépend de sous parties de
l'autre... et j'aimerai si possible éviter de multiplier mes arguments
templates. Y a t'il un moyen d'écrire quelque chose du genre :
class A;
class B{
// j'utilise des types définis dans A
^^^^^ plus sûrement des méthodes / propriétés.
};
class A { // tu vois j'ai pas menti !
// j'utilise des types définis dans B
^^^^^ idem
}
Bon, ok, ça a pas l'air bien joli niveau design... Alors si en sus
vous aviez des conseils pour éviter ce genre d'horreur.
une déclaration avec définition différée n'a rien de très laid; si de
plus les classes si définies conjointement, la relecture n'est pas gênée
par cela.
[...]
Je pense que ce qui m'a rebuté c'est le fait que ma classe A est très
grosse et que ça me gène de "gaspiller" de la place mémoire avec deux
objets quasi identiques en mémoire.
une alternative à votre approche en, est effet, de ne déclarer qu'une
seule et unique classe qui contienne toutes les informations nécessaires
à la construction des 2 ensembles de données avec 2 jeux de méthodes
d'utilisation selon le besoin externe; on pourrait pour faciliter cet
usage définir 2 classes de "travail pur", entièrement initialisée à
partir de la première et non à même de générer elle même les points /
grandeurs caractéristiques (pour ne pas dupliquer cette partie qui est
le corps de votre interdépendance actuelle).
J'ai deux classes, A et B, chacune dépend de sous parties de l'autre... et j'aimerai si possible éviter de multiplier mes arguments templates. Y a t'il un moyen d'écrire quelque chose du genre :
class A; class B{ // j'utilise des types définis dans A ^^^^^ plus sûrement des méthodes / propriétés.
}; class A { // tu vois j'ai pas menti ! // j'utilise des types définis dans B ^^^^^ idem
}
Bon, ok, ça a pas l'air bien joli niveau design... Alors si en sus vous aviez des conseils pour éviter ce genre d'horreur.
une déclaration avec définition différée n'a rien de très laid; si de plus les classes si définies conjointement, la relecture n'est pas gênée par cela.
[...] Je pense que ce qui m'a rebuté c'est le fait que ma classe A est très grosse et que ça me gène de "gaspiller" de la place mémoire avec deux objets quasi identiques en mémoire.
une alternative à votre approche en, est effet, de ne déclarer qu'une seule et unique classe qui contienne toutes les informations nécessaires à la construction des 2 ensembles de données avec 2 jeux de méthodes d'utilisation selon le besoin externe; on pourrait pour faciliter cet usage définir 2 classes de "travail pur", entièrement initialisée à partir de la première et non à même de générer elle même les points / grandeurs caractéristiques (pour ne pas dupliquer cette partie qui est le corps de votre interdépendance actuelle).
Sylvain.
meow
On doit la se comprendre... En fait j'ai deux problèmes, le premier technique, et le second plutot design. Commençons par le premier :
class A;
class B{ A a; public: B(A aa):a(aa){} A& get () {return a;} };
class A{ int i; public: A(int I):i(I){} int get () {return i;} };
int main () { B b(A(15)); std::cout<<b.get().get()<<std::endl; }
ne compile pas :
/home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp:6: error: field 'a' has incomplete type /home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp: In constructor 'B::B(A)': /home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp:8: error: 'aa' has incomplete type /home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp:3: error: forward declaration of 'struct A' /home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp:8: error: class 'B' does not have any field named 'a' /home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp: In constructor 'B::B(A)': /home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp:8: error: 'aa' has incomplete type /home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp:3: error: forward declaration of 'struct A' /home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp: In constructor 'B::B(A)': /home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp:8: error: 'aa' has incomplete type /home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp:3: error: forward declaration of 'struct A' /home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp: In member function 'A& B::get()': /home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp:9: error: 'a' was not declared in this scope
d'où ma première question : comment on fait ce genre de choses ?
On doit la se comprendre... En fait j'ai deux problèmes, le premier
technique, et le second plutot design.
Commençons par le premier :
class A;
class B{
A a;
public:
B(A aa):a(aa){}
A& get () {return a;}
};
class A{
int i;
public:
A(int I):i(I){}
int get () {return i;}
};
int main () {
B b(A(15));
std::cout<<b.get().get()<<std::endl;
}
ne compile pas :
/home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp:6:
error: field 'a' has incomplete type
/home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp: In
constructor 'B::B(A)':
/home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp:8:
error: 'aa' has incomplete type
/home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp:3:
error: forward declaration of 'struct A'
/home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp:8:
error: class 'B' does not have any field named 'a'
/home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp: In
constructor 'B::B(A)':
/home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp:8:
error: 'aa' has incomplete type
/home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp:3:
error: forward declaration of 'struct A'
/home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp: In
constructor 'B::B(A)':
/home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp:8:
error: 'aa' has incomplete type
/home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp:3:
error: forward declaration of 'struct A'
/home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp: In
member function 'A& B::get()':
/home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp:9:
error: 'a' was not declared in this scope
d'où ma première question : comment on fait ce genre de choses ?
On doit la se comprendre... En fait j'ai deux problèmes, le premier technique, et le second plutot design. Commençons par le premier :
class A;
class B{ A a; public: B(A aa):a(aa){} A& get () {return a;} };
class A{ int i; public: A(int I):i(I){} int get () {return i;} };
int main () { B b(A(15)); std::cout<<b.get().get()<<std::endl; }
ne compile pas :
/home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp:6: error: field 'a' has incomplete type /home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp: In constructor 'B::B(A)': /home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp:8: error: 'aa' has incomplete type /home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp:3: error: forward declaration of 'struct A' /home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp:8: error: class 'B' does not have any field named 'a' /home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp: In constructor 'B::B(A)': /home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp:8: error: 'aa' has incomplete type /home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp:3: error: forward declaration of 'struct A' /home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp: In constructor 'B::B(A)': /home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp:8: error: 'aa' has incomplete type /home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp:3: error: forward declaration of 'struct A' /home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp: In member function 'A& B::get()': /home/schwarz/Bacasable/workspace/Exemples/Class_forward_def.cpp:9: error: 'a' was not declared in this scope
d'où ma première question : comment on fait ce genre de choses ?
Fabien LE LEZ
On Mon, 02 Jul 2007 01:37:29 -0700, meow :
B(A aa):a(aa){}
On passe généralement les arguments par référence constante (sauf pour les types de base, comme int et les pointeurs).
B (A const& a_) : a (a_) {}
Par ailleurs, ton B contient un A. Ce qui signifie que A doit être définie avant B :
class B;
class A { // A peut contenir des B&, des B*, mais pas de B };
class B { // B peut contenir un A. };
Si tu définis les contenus avant les contenants, tu n'auras aucun souci.
Tu noteras que si un B contient un A, un A ne peut pas contenir de B.
On Mon, 02 Jul 2007 01:37:29 -0700, meow <schwarz.ben@gmail.com>:
B(A aa):a(aa){}
On passe généralement les arguments par référence constante (sauf pour
les types de base, comme int et les pointeurs).
B (A const& a_) : a (a_) {}
Par ailleurs, ton B contient un A. Ce qui signifie que A doit être
définie avant B :
class B;
class A
{
// A peut contenir des B&, des B*, mais pas de B
};
class B
{
// B peut contenir un A.
};
Si tu définis les contenus avant les contenants, tu n'auras aucun
souci.
Tu noteras que si un B contient un A, un A ne peut pas contenir de B.
On passe généralement les arguments par référence constante (sauf pour les types de base, comme int et les pointeurs).
B (A const& a_) : a (a_) {}
Par ailleurs, ton B contient un A. Ce qui signifie que A doit être définie avant B :
class B;
class A { // A peut contenir des B&, des B*, mais pas de B };
class B { // B peut contenir un A. };
Si tu définis les contenus avant les contenants, tu n'auras aucun souci.
Tu noteras que si un B contient un A, un A ne peut pas contenir de B.
Jean-Marc Bourguet
meow writes:
On doit la se comprendre... En fait j'ai deux problèmes, le premier technique, et le second plutot design. Commençons par le premier :
class A;
class B{ A a; public: B(A aa):a(aa){} A& get () {return a;} };
class A{ int i; public: A(int I):i(I){} int get () {return i;} };
int main () { B b(A(15)); std::cout<<b.get().get()<<std::endl; }
ne compile pas :
Pour avoir un membre d'un type donne, il faut avoir vu la definition (et pas uniquement la declaration) du type. Ici quand tu definis B, tu n'as vu qu'une declaration de A. (Un exemple de problemes de l'absence de definition: comment calculer la taille de B si on ne connait pas celle de A?)
La declaration de la destination suffit pour des pointeurs et des references, elle suffit aussi pour la declaration de fonctions ayant ce type en parametre.
A+
-- Jean-Marc FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html Site de usenet-fr: http://www.usenet-fr.news.eu.org
meow <schwarz.ben@gmail.com> writes:
On doit la se comprendre... En fait j'ai deux problèmes, le premier
technique, et le second plutot design.
Commençons par le premier :
class A;
class B{
A a;
public:
B(A aa):a(aa){}
A& get () {return a;}
};
class A{
int i;
public:
A(int I):i(I){}
int get () {return i;}
};
int main () {
B b(A(15));
std::cout<<b.get().get()<<std::endl;
}
ne compile pas :
Pour avoir un membre d'un type donne, il faut avoir vu la definition (et
pas uniquement la declaration) du type. Ici quand tu definis B, tu n'as vu
qu'une declaration de A. (Un exemple de problemes de l'absence de
definition: comment calculer la taille de B si on ne connait pas celle de A?)
La declaration de la destination suffit pour des pointeurs et des
references, elle suffit aussi pour la declaration de fonctions ayant ce
type en parametre.
A+
--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
On doit la se comprendre... En fait j'ai deux problèmes, le premier technique, et le second plutot design. Commençons par le premier :
class A;
class B{ A a; public: B(A aa):a(aa){} A& get () {return a;} };
class A{ int i; public: A(int I):i(I){} int get () {return i;} };
int main () { B b(A(15)); std::cout<<b.get().get()<<std::endl; }
ne compile pas :
Pour avoir un membre d'un type donne, il faut avoir vu la definition (et pas uniquement la declaration) du type. Ici quand tu definis B, tu n'as vu qu'une declaration de A. (Un exemple de problemes de l'absence de definition: comment calculer la taille de B si on ne connait pas celle de A?)
La declaration de la destination suffit pour des pointeurs et des references, elle suffit aussi pour la declaration de fonctions ayant ce type en parametre.
A+
-- Jean-Marc FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html Site de usenet-fr: http://www.usenet-fr.news.eu.org
meow
La réponse est donc : "c'est pas possible dirrectement, il faut passer par des pointeurs". Merci. Merci aussi pour les remarques sur mon code, et oui, c'est pas parce qu'on fait une exemple rapide qu'il faut le faire laidement ;)
La réponse est donc : "c'est pas possible dirrectement, il faut passer
par des pointeurs". Merci.
Merci aussi pour les remarques sur mon code, et oui, c'est pas parce
qu'on fait une exemple rapide qu'il faut le faire laidement ;)
La réponse est donc : "c'est pas possible dirrectement, il faut passer par des pointeurs". Merci. Merci aussi pour les remarques sur mon code, et oui, c'est pas parce qu'on fait une exemple rapide qu'il faut le faire laidement ;)
meow
Après quelques essais supplémentaires...
La declaration de la destination suffit pour des pointeurs et des references, elle suffit aussi pour la declaration de fonctions ayant ce type en parametre.
Et encore... Je n'ai visiblement pas le droit de faire grand chose avec de tels pointeurs, ce qui en définitive me parrait logique. J'explicite :
class A;
class B{ A *a; public : B(){a=new A();} }
Rien que ça, ça va déjà poser problème parce qu'à ce moment le compilo n'a aucun moyen de savoir si j'ai bien un tel constructeur dans A...
Tu noteras que si un B contient un A, un A ne peut pas contenir de B.
Bein oui... Et c'est bien ce qui me désole. En fait j'ai l'impression que si le compilo mettait ces cas de figure de coté jusqu'à trouver la définition de A il aurrait l'occasion de faire les liens à ce moment, ce qui permettrait d'avoir des définitions récursives... Mais j'imagine qu'il doit y avoir des soucis que je ne vois pas :)
Concrètement maintenant, si je veux m'en sortir il semblerait qu'une méthode pourrait consister dans l'emploi d'un héritage virtuel. Genre une classe abstraite AA déclarant les fonctions virtuelles dont j'aurai besoin dans B, une classe BB déclarant les fonctions dont j'aurai besoni dans A, puis des classes A et B descendant respectivement de AA et BB et contenant respectivement un BB* et un AA* ...J'ai bon ?
Après quelques essais supplémentaires...
La declaration de la destination suffit pour des pointeurs et des
references, elle suffit aussi pour la declaration de fonctions ayant ce
type en parametre.
Et encore... Je n'ai visiblement pas le droit de faire grand chose
avec de tels pointeurs, ce qui en définitive me parrait logique.
J'explicite :
class A;
class B{
A *a;
public :
B(){a=new A();}
}
Rien que ça, ça va déjà poser problème parce qu'à ce moment le compilo
n'a aucun moyen de savoir si j'ai bien un tel constructeur dans A...
Tu noteras que si un B contient un A, un A ne peut pas contenir de B.
Bein oui... Et c'est bien ce qui me désole.
En fait j'ai l'impression que si le compilo mettait ces cas de figure
de coté jusqu'à trouver la définition de A il aurrait l'occasion de
faire les liens à ce moment, ce qui permettrait d'avoir des
définitions récursives... Mais j'imagine qu'il doit y avoir des soucis
que je ne vois pas :)
Concrètement maintenant, si je veux m'en sortir il semblerait qu'une
méthode pourrait consister dans l'emploi d'un héritage virtuel.
Genre une classe abstraite AA déclarant les fonctions virtuelles dont
j'aurai besoin dans B, une classe BB déclarant les fonctions dont
j'aurai besoni dans A, puis des classes A et B descendant
respectivement de AA et BB et contenant respectivement un BB* et un
AA*
...J'ai bon ?
La declaration de la destination suffit pour des pointeurs et des references, elle suffit aussi pour la declaration de fonctions ayant ce type en parametre.
Et encore... Je n'ai visiblement pas le droit de faire grand chose avec de tels pointeurs, ce qui en définitive me parrait logique. J'explicite :
class A;
class B{ A *a; public : B(){a=new A();} }
Rien que ça, ça va déjà poser problème parce qu'à ce moment le compilo n'a aucun moyen de savoir si j'ai bien un tel constructeur dans A...
Tu noteras que si un B contient un A, un A ne peut pas contenir de B.
Bein oui... Et c'est bien ce qui me désole. En fait j'ai l'impression que si le compilo mettait ces cas de figure de coté jusqu'à trouver la définition de A il aurrait l'occasion de faire les liens à ce moment, ce qui permettrait d'avoir des définitions récursives... Mais j'imagine qu'il doit y avoir des soucis que je ne vois pas :)
Concrètement maintenant, si je veux m'en sortir il semblerait qu'une méthode pourrait consister dans l'emploi d'un héritage virtuel. Genre une classe abstraite AA déclarant les fonctions virtuelles dont j'aurai besoin dans B, une classe BB déclarant les fonctions dont j'aurai besoni dans A, puis des classes A et B descendant respectivement de AA et BB et contenant respectivement un BB* et un AA* ...J'ai bon ?
N'oublie pas le point-virgule à la fin de la définition de la classe !
class A;
class B { public: B(); private: A* a; };
class A { ... };
B::B() : a (0) { a= new A; }
Fabien LE LEZ
On Mon, 02 Jul 2007 04:26:48 -0700, meow :
Tu noteras que si un B contient un A, un A ne peut pas contenir de B.
Bein oui... Et c'est bien ce qui me désole.
Mais pour le coup, ça n'a rien à voir avec une restriction du compilateur.
Si un B contient un A, il est forcément plus grand que le A. Si un A contient un B, il est forcément plus grand que le B. Du coup, si un A contient un B qui lui-même contient un A, l'objet A est plus grand que lui-même.
On Mon, 02 Jul 2007 04:26:48 -0700, meow <schwarz.ben@gmail.com>:
Tu noteras que si un B contient un A, un A ne peut pas contenir de B.
Bein oui... Et c'est bien ce qui me désole.
Mais pour le coup, ça n'a rien à voir avec une restriction du
compilateur.
Si un B contient un A, il est forcément plus grand que le A.
Si un A contient un B, il est forcément plus grand que le B.
Du coup, si un A contient un B qui lui-même contient un A, l'objet A
est plus grand que lui-même.
Tu noteras que si un B contient un A, un A ne peut pas contenir de B.
Bein oui... Et c'est bien ce qui me désole.
Mais pour le coup, ça n'a rien à voir avec une restriction du compilateur.
Si un B contient un A, il est forcément plus grand que le A. Si un A contient un B, il est forcément plus grand que le B. Du coup, si un A contient un B qui lui-même contient un A, l'objet A est plus grand que lui-même.