IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

inclusion cyclique et compilation


Sujet :

C++

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 6
    Points : 3
    Points
    3
    Par défaut inclusion cyclique et compilation
    Bonjour,

    malgré mes recherches je ne suis pas certain d'avoir bien compris les raisons qui font que parfois lors d'inclusions cycliques il y a erreur de compilation.

    J'ai fait quelque petits tests:

    Soit la classe A :

    A.h:

    #ifndef A_H_
    #define A_H_

    #include "B.h"

    class A {

    public:
    void a(B b);

    };

    #endif
    et la classe B :

    B.h:
    #ifndef B_H_
    #define B_H_

    #include "A.h"

    class B {

    public:
    void b();

    };

    #endif

    Ca ne compile donc pas avec l'erreur suivante:

    In file included from B.h:11,
    from B.cpp:9:
    A.h:16: error: ‘B’ has not been declared
    Ce que j'interprète comme ça:

    Dans B.cpp, avec la directive d'inclusion le préprocesseur copie-colle B.h et le parse :

    or B.h inclut A.h donc le préprocesseur copie-colle aussi A.h et le parse:

    il rencontre le symbole "B" dans la fonction "void a(B b)", le compilo veut connaitre l'adresse mémoire de ce symbole (via la table des symboles) mais il ne peut pas car la classe B n'a pas encore été compilée.

    Est ce que c'est vraiment ce qu'il se passe ?

    Si oui alors pourquoi après:
    - avoir enlevé le symbole B de ma classe A pour avoir simplement "void a()".
    - et utiliser le symbole B dans ma classe B , par exemple avec une fonction "void b(B b);"

    pourquoi est ce que ça compile ? ca ne devrait pas puisqu'il ne connait toujours pas l'adresse du symbole B...??...

  2. #2
    Membre chevronné
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Points : 2 107
    Points
    2 107

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 6
    Points : 3
    Points
    3
    Par défaut
    merci chef mais j'avais bien compris comment résoudre le pb .

    Ce qui m'intéresse c'est la "sauce interne"du compilo pour ne pas appliquer bêtement les solutions ^^ .

    Par exemple:

    on va simplement déclarer celle-ci pour indiquer au compilateur qu'elle existe. Cela marche car tant qu'on n'utilise qu'un pointeur ou une référence, le compilateur n'a pas besoin de connaître en détail le contenu de la classe. Il a juste besoin de savoir qu'elle existe. Par contre au moment d'utiliser celle-ci (appel d'une fonction membre par exemple) il faudra bien avoir inclus son en-tête, mais ce sera fait dans le .cpp et non plus dans le .h,
    Ce sont certainement de bonnes recettes mais concrètement ca signifie quoi au niveau de l'analyse lexicale et syntaxique du compilo ? de la table des symboles ?

  4. #4
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut, et bienvenue sur le forum.

    La "sauce interne" du compilateur est simple: il parcourt ton code de haut en bas, et de gauche à droite, exactement comme la manière dont tu parcours un roman qui te plait

    Et, tout comme tu ignore ce qui se passe à la page 12 quand tu n'a lu que les dix premières, le compilateur ne connait que ce qu'il a déjà rencontré (il ne connait que ce qui a été déclaré ou défini dans les lignes précédentes).

    Tant que le compilateur n'a pas besoin de savoir de quoi est composée une classe, il peut donc se contenter de... savoir que la classe en question existe.

    Et, pour lui dire que la classe existe, il "suffit" de... la déclarer (c'est ce que l'on appelle la "déclaration anticipée") sous la forme de
    Evidemment, une fois dés qu'il est question pour le compilateur de savoir l'espace que la classe prend en mémoire ou, de manière générale, d'accéder au contenu de la classe, le seul fait de savoir qu'elle existe ne suffit plus: il doit... savoir de quoi elle est composée.

    Il doit donc à ce moment là disposer... de la définition de la classe.

    Maintenant, intéressons nous un peu à ce que fait le compilateur.

    Pour que tu comprenne le principe, il faut savoir qu'il y a trois grandes étapes à la compilation:
    1. La gestion des directives préprocesseur
    2. La génération d'un code binaire
    3. l'édition de liens
    Tout le problème des inclusions cycliques trouve son origine dans la première étape.

    Pour que nous parlions la même langue, nous pouvons dire que toute ligne qui commence par un "#" est une instruction préprocesseur, et tout se joue sur les directive #include.

    Lorsque le préprocesseur rencontre une directive #include, recopie litéralement l'ensemble du fichier dont le nom est donné en lieu et place de la dite directive.

    Seulement, cette directive s'applique de manière récursive (si a.hpp inclus b.hpp qui inclus c.hpp qui inclus d.hpp, nous retrouverons dans a.hpp le contenu de b.hpp, de c.hpp et de d.hpp )

    Si nous avons deux fichiers d'en-tête (faisons simple: a.hpp et b.hpp) qui ressemble à
    a.hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #ifndef A_HPP
    #define A_HPP
    #include "b.hpp"
    class A
    {
        /*...*/
    };
    #endif // A_HPP
    et à b.hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #ifndef B_HPP
    #define B_HPP
    #include "a.hpp"
    class b
    {
        /*...*/
    };
    #endif // B_HPP
    lorsque le préprocesseur va travailler, nous aurons quelque chose dont le résultat ressemblera fort à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    /* début de a.hpp */
    #ifndef A_HPP
    #define A_HPP
    /* la directive #include b.hpp est remplacée par le contenu du fichier en 
     * question
     */
    #ifndef B_HPP
    #define B_HPP
    /* ici vient normalement... la directive #include a.hpp qui est donc...
     * remplacée par le contenu du fichier
     */
    #ifndef A_HPP
    #define A_HPP
    /* ici vient normalement ...
     * bref, on peut continuer 106 ans de la sorte :P
     */
    Ce n'est qu'après cette étape de remplacement des directives include (qui finit en cercle vicieux) qu'une deuxième étape va gérer les gardes anti inclusions et faire en sorte... de supprimer les parties correspondant aux symboles déjà défini.

    Mais, encore faut il arriver à sortir de cette inclusion cyclique, et il n'y a, malheureusement, aucun moyen d'y arriver

    C'est la raison pour laquelle, si deux classes font référence l'une à l'autre, il faut trouver un "autre moyen" de travailler.

    Cet autre moyen est, finalement, relativement simple:
    nous déclarons anticipativement la classe A dans b.hpp et la classe B dans a.hpp
    nous n'utilisons que des pointeurs ou des références vers la classe B dans a.hpp et vers la classe A dans b.hpp
    nous incluons le fichier d'en-tête (a.hpp et b.hpp) dans... le fichier d'implémentation (respectivement b.cpp et a.cpp), c'est à dire, "le plus tard possible" par rapport au moment où... le compilateur doit disposer du contenu des deux classes.

    Au final, les fichiers ressemblent donc à
    fichier a.hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #ifndef A_HPP
    #define A_HPP
    class B; // juste la déclaration, cela suffit ici vu qu'il faut juste que le 
             // compilateur sache qu'elle existe
    class A
    {
        public:
             void foo();
        private:
            B * b_; // la taille utilisée en mémoire par n'importe quel pointeur est
                    // connue, même si elle dépend du système
    };
    #endif // A_HPP
    fichier b.hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #ifndef B_HPP
    #define B_HPP
    class A; // juste la déclaration, cela suffit ici vu qu'il faut juste que le 
             // compilateur sache qu'elle existe
    class B
    {
        public:
             void bar();
        private:
            A * a_; // la taille utilisée en mémoire par n'importe quel pointeur est
                    // connue, même si elle dépend du système
    };
    #endif // B_HPP
    fichier a.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    /* il faut que le compilateur connaisse le contenu de la classe A,
     * vu que l'on définit... les fonctions de A ;)
     */
    #include "a.hpp"
    /* et il doit connaitre le contenu de la classe B (pour pouvoir invoquer bar
     * depuis le pointeur sur B qui existe dans A)
     */
    #include "b.hpp"
    void A::foo()
    {
        b_->bar();
    }
    fichier b.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    /* il faut que le compilateur connaisse le contenu de la classe B,
     * vu que l'on définit... les fonctions de B ;)
     */
    #include "b.hpp"
    /* et il doit connaitre le contenu de la classe A (pour pouvoir invoquer foo
     * depuis le pointeur sur A qui existe dans B)
     *
     * en pratique, il n'y aura sans doute pas une telle récursivité, ou il y
     * aura des tests permettant d'y mettre fin :D
     */
    #include "a.hpp"
    void b::bar()
    {
        a_->foo();
    }
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 6
    Points : 3
    Points
    3
    Par défaut
    merci pour la longue réponse .

    Cependant je m'excuse mais ce n'est pas très clair. Je crois que j'ai compris le système des #ifndef... mais mon problème se pose plus sur la résolution des symboles par le compilateur

    Par exemple la phrase suivante:
    // la taille utilisée en mémoire par n'importe quel pointeur est connue, même si elle dépend du système
    Je suis entièrement d'accord avec ça, mais alors pourquoi par exemple le code suivant va compiler ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #ifndef B_H_
    #define B_H_
     
     
    class B {
     
    public:
    	void f(B b);  //à ce stade on ne sait pas non plus la taille 
    //que va prendre B en mémoire puisque la classe B n'a pas fini de compiler non ?
    };
     
    #endif

  6. #6
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par qertbu65 Voir le message
    merci pour la longue réponse .

    Cependant je m'excuse mais ce n'est pas très clair. Je crois que j'ai compris le système des #ifndef... mais mon problème se pose plus sur la résolution des symboles par le compilateur

    Par exemple la phrase suivante:


    Je suis entièrement d'accord avec ça, mais alors pourquoi par exemple le code suivant va compiler ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #ifndef B_H_
    #define B_H_
     
     
    class B {
     
    public:
    	void f(B b);  //à ce stade on ne sait pas non plus la taille 
    //que va prendre B en mémoire puisque la classe B n'a pas fini de compiler non ?
    };
     
    #endif
    Si tu sais pertinemment la taille que va prendre la classe, parce que tu te trouve dans le bloc de définition de la classe.

    Par contre, tu auras un problème avec un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    class B;
    void foo(B b) // le problème intervient ici :D
    {
        b.bar();
    }
    class B
    {
        public:
            void bar(){cout<<"B::bar()"<<endl;}
    };
    parce que le compilateur sait qu'il existe un type B quand il croise foo(B b), mais il ne dispose pas du type complet. (error 'B' has incomplete type)
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  7. #7
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    à noter :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    class C;
    void f(B b); // Ok
     
    void g(B b) {} // Pas ok
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  8. #8
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    à noter :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    class C;
    void f(B b); // Ok
     
    void g(B b) {} // Pas ok
    Sauf que f(B b); avec un déclaration anticipée de C...
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  9. #9
    Candidat au Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 6
    Points : 3
    Points
    3
    Par défaut
    Si tu sais pertinemment la taille que va prendre la classe, parce que tu te trouve dans le bloc de définition de la classe.
    Hmmm je crois que ça s'éclaire petit à petit .


    Cependant, après relecture je ne suis pas convaincu () du fonctionnement des mécanismes d'inclusions et des gardes tel que décrit :

    Ce n'est qu'après cette étape de remplacement des directives include (qui finit en cercle vicieux) qu'une deuxième étape va gérer les gardes anti inclusions et faire en sorte... de supprimer les parties correspondant aux symboles déjà défini.

    Mais, encore faut il arriver à sortir de cette inclusion cyclique, et il n'y a, malheureusement, aucun moyen d'y arriver
    j'ai fait le test suivant:

    A.h:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #ifndef A_H_
    #define A_H_
     
    #include "B.h"
     
    class A {
     
    public:
    	void a();
     
    };
     
    #endif
    et

    B.h:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    #ifndef B_H_
    #define B_H_
     
    #include "A.h"
     
    class B {
     
    public:
    	void b();
     
    };
     
    #endif
    D'après ce que j'ai compris il ne devrait pas non plus sortir des ces inclusions cycliques donc ?

    Mais pourtant ça compile ?



    (De plus en lisant ce lien http://en.wikipedia.org/wiki/Include_guard j'ai l'impression que le compilo évalue les directives du préprocesseur (donc les #include , #ifndef et #define ) au fil de l'eau et non pas en 2 étapes comme tu as dit :

    Here, the first inclusion of "grandfather.h" causes the macro GRANDFATHER_H to be defined. Then, when "child.c" includes "grandfather.h" the second time, the #ifndef test fails, and the preprocessor skips down to the #endif, thus avoiding the second definition of struct foo. The program compiles correctly.
    Ou alors wikipedia se gourre mais alors pourquoi mon exemple compile ? )

  10. #10
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par qertbu65 Voir le message
    Hmmm je crois que ça s'éclaire petit à petit .


    Cependant, après relecture je ne suis pas convaincu () du fonctionnement des mécanismes d'inclusions et des gardes tel que décrit :



    j'ai fait le test suivant:

    A.h:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #ifndef A_H_
    #define A_H_
     
    #include "B.h"
     
    class A {
     
    public:
    	void a();
     
    };
     
    #endif
    et

    B.h:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    #ifndef B_H_
    #define B_H_
     
    #include "A.h"
     
    class B {
     
    public:
    	void b();
     
    };
     
    #endif
    D'après ce que j'ai compris il ne devrait pas non plus sortir des ces inclusions cycliques donc ?

    Mais pourtant ça compile ?



    (De plus en lisant ce lien http://en.wikipedia.org/wiki/Include_guard j'ai l'impression que le compilo évalue les directives du préprocesseur (donc les #include , #ifndef et #define ) au fil de l'eau et non pas en 2 étapes comme tu as dit :



    Ou alors wikipedia se gourre mais alors pourquoi mon exemple compile ? )
    Mais là, tu ne fais pas référence à ta classe B dans ta classe A et inversément... ( ce qui fait que l'inclusion est totalement inutile)

    Le fait est que, de toutes manières, quel que soit l'ordre dans lequel tu envisages les choses, si tu as deux classes proches de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class A
    {
        /*...*/
        private:
            B b;
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class B
    {
        private:
            A a;
    };
    tu te trouve face à la nécessité de ... connaître la taille de l'un pour déterminer la taille de l'autre.

    Les gardes anti inclusions multiples joueront sans doute leur rôle, mais il y en aura toujours un qui sera... défini avant l'autre, et tu rentre dans un cercle vicieux parce que tu as besoin de connaitre... la taille de celui qui est défini après:

    Pour déterminer la taille de A, tu as besoin de connaitre la taille de B, mais, pour déterminer la taille de B, tu as besoin de connaitre la taille de A, qui nécessite de connaitre... la taille de B, qui nécessite... de connaitre la taille de A (et je pourrais continuer éternellement de la sorte).

    C'est pourquoi, la seule manière d'éviter cette dépendance cyclique est... d'utiliser un système qui a une empreinte mémoire différente (un pointeur, par exemple, qui sera systématiquement composé d'un nombre donné de bytes (4 ou 8, de manière classique) ou une référence, dont on ne peut pas prendre l'adresse et qui est représenté au niveau du code binaire comme un pointeur "bien caché")
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  11. #11
    Candidat au Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 6
    Points : 3
    Points
    3
    Par défaut
    oui ! je crois que c'est cela !
    C'est bien je pense pour le compilo un problème de connaissance de la taille !

    Sinon, sauf votre respect chef, je crois que wikipedia a raison sur le fonctionnement des includes.
    De plus, je crois également que ça n'a rien à voir avec le fait que cette affaire de "classes appelées circulairement" ne fonctionne pas (je ne veux pas/plus dire "inclusions circulaires" car le pb ne vient pas des includes, bien qu'ils amènent le problème, mais bien de la connaissance des tailles de chaque classe par le compilo, et dire que c'est un pb "d'inclusions circulaires" ca fait confondre et laisser penser que le pb vient des includes, 'fin bon je disgresse :p) .

    J'ai bon ?

    Si oui je vais un peu méditer là-dessus avant de passer le thread en résolu.

    merci en tout cas !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Typedef et inclusion cyclique
    Par Johjo dans le forum Langage
    Réponses: 7
    Dernier message: 22/10/2010, 14h33
  2. d'inclusion cyclique et makefile
    Par vincent.mbg dans le forum C
    Réponses: 4
    Dernier message: 14/06/2010, 18h05
  3. probleme inclusion cyclique avec namespace
    Par befalimpertinent dans le forum C++
    Réponses: 4
    Dernier message: 27/05/2010, 09h52
  4. problème inclusion cyclique
    Par marion5515 dans le forum Débuter
    Réponses: 7
    Dernier message: 20/05/2009, 13h53
  5. Inclusion cyclique: mauvaise analyse?
    Par zabibof dans le forum C++
    Réponses: 4
    Dernier message: 12/09/2007, 16h36

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo