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 headers dans un header


Sujet :

C++

  1. #1
    Membre régulier
    Inscrit en
    Juin 2008
    Messages
    140
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 140
    Points : 103
    Points
    103
    Par défaut Inclusion headers dans un header
    Bonjour,

    Je souhaite connaitre le moyen recommandé d'inclusion d'un certain type de header dont voici l'exemple :
    J'ai un header contenant une énumération que j'utilise beaucoup:
    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    // Mon fichier "MyEnum.hpp"
    enum RESULTS {OK, KO};
    J'utilise ensuite très souvent cette énumération comme, par exemple, un retour d'une méthode d'une classe:
    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // Mon fichier "MyClass.hpp"
    class MyClass
    {
      // Les attributs
      // ...
     
      // Les méthodes
      // ...
     
      // dont celle retournant une valeur de l'énumération
      RESULTS MyMethod( void );
    };
    Où dois-je inclure le fichier "MyEnum.hpp" ?
    - Dans le header "MyClass.hpp"
    - Dans le source "MyClass.cpp" et avant l'inclusion de "MyClass.hpp"

    Merci et bonne journée.

  2. #2
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Essaye de ne pas inclure "Enum.hpp" dans "MyClass.hpp" puis inclus "MyClass.hpp" dans "main.cpp" et de essayer d'utiliser ta classe MyClass. Regarde les messages d'erreur et pose-toi la question de comment tu veux que les gens utilisent ta classe (et donc le fichier header qui va avec)

  3. #3
    Membre régulier
    Inscrit en
    Juin 2008
    Messages
    140
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 140
    Points : 103
    Points
    103
    Par défaut
    Citation Envoyé par Bktero Voir le message
    Essaye de ne pas inclure "Enum.hpp" dans "MyClass.hpp" puis inclus "MyClass.hpp" dans "main.cpp" et de essayer d'utiliser ta classe MyClass. Regarde les messages d'erreur
    Comme cela :
    Mon fichier "MyEnum.hpp"
    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    enum RESULTS {OK, KO};
    Mon fichier "MyClass.hpp"
    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class MyClass
    {
      // Les attributs
      // ...
     
      // Les méthodes
      // ...
     
      // dont celle retournant une valeur de l'énumération
      RESULTS MyMethod( void );
    };
    Mon fichier "MyClass.cpp"
    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #include "MyEnum.hpp"
    #include "MyClass.hpp"
     
    RESULTS MyClass::MyMethod( void )
    {
      // Do something
      return OK;
    }
    Mon fichier "main.cpp"
    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #include "MyEnum.hpp"
    #include "MyClass.hpp"
     
    int main( void )
    {
      // ...
      MyClass MC;
      // ...
      if ( OK == MC.MyMethod()
      {
         // Do something
      }
      return OK;
    }

    Citation Envoyé par Bktero Voir le message
    pose-toi la question de comment tu veux que les gens utilisent ta classe (et donc le fichier header qui va avec)
    De ce point de vue là oui tout à fait.
    D'où ma question initiale.

    Merci pour ta réponse.

  4. #4
    Membre expérimenté

    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 685
    Points : 1 418
    Points
    1 418
    Par défaut
    Mon fichier "MyClass.cpp"

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #include "MyEnum.hpp"
    #include "MyClass.hpp"
     
    RESULTS MyClass::MyMethod( void )
    {
      // Do something
      return OK;
    }
    Si tu inclus MyEnum.hpp dans MyClass.hpp et que tu inclus MyClass.hpp dans MyClass.cpp, tu n'as pas besoin de le réinclure à côté de MyClass.hpp. Idem pour le main.
    Nullius in verba

  5. #5
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 565
    Points : 7 648
    Points
    7 648
    Par défaut
    Les includes c'est compliqué! Pourtant il suffit d'appliquer une règle simple : "un fichier doit inclure tout ce dont il a besoin et pas d'autres choses".
    Pour les entêtes on doit ajouter : "et on doit se protéger de la réentrance".

    Il existe des entêtes spéciaux qui eux n'ont pas de besoin mais ne servent qu'à regrouper des besoins. La contrainte est que ces entêtes globaux ne doivent pas être inclus dans un entête (car ils contreviennent surement à la seconde partie de la règle.)

    Un moyen simple de vérifier la première partie de la phrase pour les entêtes : écrire un fichier source qui n'inclut que l'include, il doit compiler.
    Un moyen de vérifier la seconde partie, supprimer un après l'autres les includes, si ça compile toujours, on peut l'ôter.

    Donc ici : MyEnum.hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #pragma once       // indispensable
    enum RESULTS {OK, KO};
    MyClass.hpp:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #pragma once           // indispensable
    #include "MyEnum.hpp"  // indispensable
    class MyClass
    {
       ... ... 
       ... RESULTS ...  // utilise RESULTS donc à besoin de MyEnum.hpp
       ... ...
    };
    MyClass.cpp ou bien Main.cpp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #include "MyEnum.hpp"  // facultatif (on utilise RESULTS, mais forcément "MyClass.hpp" aussi)
    #include "MyClass.hpp" // indispensable
       ... ...
       ... MyClass ...   // utilise MyClass donc à besoin de MyClass.hpp         
       ... ... 
       ... RESULTS ...   // utilise RESULTS donc à besoin de MyEnum.hpp
       ... ...

  6. #6
    Membre régulier
    Inscrit en
    Juin 2008
    Messages
    140
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 140
    Points : 103
    Points
    103
    Par défaut
    Citation Envoyé par Kaamui Voir le message
    Si tu inclus MyEnum.hpp dans MyClass.hpp et que tu inclus MyClass.hpp dans MyClass.cpp, tu n'as pas besoin de le réinclure à côté de MyClass.hpp. Idem pour le main.
    Oui tout à fait.
    Néanmoins si beaucoup de classes ont des méthodes renvoyant ce type, alors dans par exemple ma fonction main, j'aurais plusieurs fois inclut ce même fichier "MyEnum.hpp". Même en utilisant le #ifndef pour éviter des redéclarations, cela peut faire beaucoup de fois le même fichier inclut dans un fichier .cpp.

  7. #7
    Membre expérimenté

    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 685
    Points : 1 418
    Points
    1 418
    Par défaut
    Citation Envoyé par MicBeastKiller Voir le message
    Oui tout à fait.
    Néanmoins si beaucoup de classes ont des méthodes renvoyant ce type, alors dans par exemple ma fonction main, j'aurais plusieurs fois inclut ce même fichier "MyEnum.hpp".

    D'où la réponse de @Bktero qui t'invites à bien réfléchir à tout ça. Si tu structures correctement ton code, tu ne devrais pas avoir trop de souci. Par exemple, si tu n'avais pas eu besoin d'inclure "MyEnum.hpp" dans "MyClass.hpp" car pas du tout utilisé (en l'occurence là il est nécessaire pour reconnaître ton type énuméré en type de retour de ta fonction), alors tu l'aurais inclus directement dans le fichier "MyClass.cpp".

    L'essentiel est de bien comprendre que l'inclusion de fichier est faite pour que le compilateur puisse identifier chaque mot correctement, et qu'il faut alors juste se concentrer sur "qui utilise quoi ?".

    Même en utilisant le #ifndef pour éviter des redéclarations, cela peut faire beaucoup de fois le même fichier inclut dans un fichier .cpp
    Oui mais avec ces directives, la compilation ira jusqu'au bout. Le seul risque a tout inclure partout et à tout va, c'est juste d'augmenter le temps que va mettre la compilation à "parser" le code, et de rendre le code moins compréhensible. En soit, rien n'empêche d'inclure absolument tout partout tout le temps.
    Nullius in verba

  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
    Salut,

    De manière générale, tu ne dois inclure un fichier d'en-tête (*.hpp) que "le plus tard possible", lorsque tu en as réellement besoin. C'est à dire:

    • "Autant que possible" dans le fichier d'implémentation (*.cpp), car c'est là que tu créeras le plus de variable, que tu feras le plus appel aux fonctions déclarée dans le fichier d'en-tête
    • Dans le fichier d'en-tête lorsque tu n'as pas d'autre choix; lorsque tu veux créer une donnée membre de classe ou de structure dont le type correspond à une classe définie dans un autre fichier d'en-tête, par exemple.

    Il faut savoir que le compilateur n'acceptera de travailler qu'avec ce qu'il connaît, qu'il lit les lignes "dans l'ordre où elles arrivent" (de la même manière que toi, tu lis un livre : de la première page à la dernière) et qu'il ne connaît que le contenu des lignes qu'il a déjà lues (à quelques exceptions près).

    Il faut aussi savoir que le compilateur va systématiquement essayer de calculer la taille qu'une classe ou une structure nécessite pour être représentée en mémoire, pour s'assurer qu'aucune donnée qui compose la structure ne risque de se retrouver à une adresse mémoire "utilisée par une autre donnée".

    Or, la taille d'une structure (ou d'une classe) correspond à la somme de la taille de toutes les données qu'elle contient ( et de quelques éléments d'alignement destiné à faciliter l'accès aux données les "plus petites"), alors que le compilateur ne connaît "par défaut" (comprend : sans qu'on ne lui dise rien) que la taille des "types primitifs" (char, short, int, long, long long, dans leur version signée et non signée ainsi que float, double et long double), qu'il connaît d'ailleurs automatiquement parce qu'il s'agit de mots clé

    Ainsi, le compilateur n'aura absolument aucun mal à évaluer la taille nécessaire à la représentation en mémoire d'une structure proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    struct Point{
        int x;
        int y;
    };
    parce qu'il connait la taille d'un int, et qu'il peut donc assez facilement évaluer la taille de la structure Point à ... deux fois la taille d'un int (quelle que soit la taille d'un int sur une architecture donnée)

    Seulement, quand tu vas vouloir déclarer une donnée de type Point, sous une forme qui pourrait être proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int main(){
        Point p;
    }
    il faudra que le compilateur sache
    1. Que le terme "Point" existe et peut être utilisé
    2. que le terme "Point" correspond effectivement à un type de donnée (et non à une fonction ou à une variable quelconque)
    3. la taille que prendra la variable p en mémoire

    Et, plus que tout, lorsque tu voudras essayer d'accéder à la donnée x (ou y ) de p, sous une forme qui pourrait être proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int main(){
        Point p;
        p.x = 15;
        p.y = 20;
    }
    il faudra -- forcément -- qu'il sache:
    1. que x (ou y) est une donnée qui compose la structure "Point"
    2. la taille que nécessite x (ou y) pour être représentée en mémoire
    3. quelles manipulations peuvent être entreprise sur x (ou sur y)

    De même, si tu décides d'ajouter une fonction à ta structure (ou à ta classe), par exemple, en donnant une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    struct Point{
        void move(int diffX, int diffY){
            x+= diffX;
            y+=diffY;
        }
        int x;
        int y;
    };
    il faudra que le compilateur sache
    1. que move est un nom qui existe
    2. que move est le nom d'une fonction
    3. que le prototype de la fonction move s'attend à recevoir deux int en paramètres

    pour qu'il accepte que tu manipule ton point (p) sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int main(){
         Point p;
        p.move(3, -5); //!!! Tel quel, le code pose quelques problèmes, sans rapport avec ce qui nous occupe !!!
    }
    En un mot comme en cent : lorsque tu veux pouvoir déclarer une donnée dont le type correspond à une structure (ou à une classe,) il faut impérativement que le compilateur sache absolument tout de la structure (ou de la classe) que tu veux utiliser.

    Cependant, il y a deux exceptions à tout ce que je viens d'expliquer:

    La première concerne les pointeurs. Car un pointeur n'est jamais qu'une valeur numérique entière (généralement non signée) qui représente l'adresse mémoire à laquelle on devrait (à laquelle on espère ) trouver une donnée du type indiqué.

    Or, la taille nécessaire pour pouvoir représenter une adresse mémoire est -- forcément -- parfaitement connue du compilateur, même si elle dépend de l'architecture sur laquelle l'application devra fonctionner (et, dans une certaine mesure, du système d'exploitation qui tourne sur l'ordinateur)

    Du coup, le compilateur peut se contenter de savoir "qu'il existe un type portant un nom particulier" lorsque tu souhaites déclarer donnée sous la forme d'un pointeur. Du moins, aussi longtemps qu'il n'a pas besoin de connaître "le reste" des informations.

    Ainsi, le compilateur pourrait très bien se contenter de savoir qu'il existe un type (qui est une structure) nommée Point lorsqu'il croise un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int main(){
        Point * ptr;
    }
    et, pour ce fare, car ce code serait refusé en l'état, nous pouvons avoir recours ce que l'on appelle une "déclaration anticipée", qui consiste "tout simplement" à... indiquer au compilateur que l'identifiant appelé Point correspond à une structure AVANT que le compilateur ne croise la déclaration de notre pointeur.

    Si bien que le code corrigé pour prendre la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    /* On indique simplement qu'il existe une structure nommée Point */
    struct Point;
    int main(){
         /* le compilateur acceptera désormais que l'on déclare un pointeur sur le type Point */
         Point * ptr;
    }
    Mais, bien sur, dés qu'il s'agira d'allouer de la mémoire pour ce pointeur, ou d'essayer d'accéder aux données (ou aux fonctions) qui composent la donnée de type Point que l'on espère trouver à l'adresse représentée par ptr, il faudra de nouveau que le compilateur connaisse absolument tout de la structure Point

    La deuxième exception correspond aux références, pour une raison toute simple : quand on descend au niveau du code binaire exécutable compréhensible par un processeur (ou au niveau du code assembleur généré par le compilateur), les références sont représentées sous forme de pointeurs.

    Les même causes ayant les mêmes effets, le compilateur connaît donc parfaitement la taille qu'une référence sur une donnée -- quel qu'en soit le type -- nécessitera pour être représentée dans le code binaire
    !!! CECI N'EST PAS UNE RAISON POUR UTILISER DES POINTEURS AU LIEU DE REFERNCES !!! IL RESTE TOUJOURS PREFERABLE DE PRIVILEGIER LES REFERENCES CHAQUE FOIS QUE FAIRE SE PEUT !!! (mais c'est un autre débat)

    Jusqu'à présent, je n'ai parlé que des classes et des structures (les mots clé class et struct) qui sont équivalent (à une très légère exception près) en C++.

    Il faut savoir que le principe est sensiblement le même en ce qui concerne les unions (le mot clé union), à l'exception de la manière dont la taille nécessaire pour les représenter en mémoire est calculée

    Le principe des énumérations et très différent, car les valeurs énumérées (tes valeur OK et KO) sont ce que l'on appelle des "constantes de compilation".

    Essayons de faire simple:

    Lorsque tu utilise le mot clé enum (par exemple sous la forme de enum RESULTS), tu dis au compilateu "on va créer un nouveau type de valeurs numériques entières nommé RESULTS", puis, quand tu déclare les identifiant correspondant aux différentes valeurs énumérées sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    enum RESULTS{
        OK,
        KO
    };
    tu indique au compilateur qu'il doit associer le terme OK à la valeur 0 (parce que tu ne précise pas d'autre valeur) et le terme KO à la valeur 1 (vu que c'est la valeur de OK +1, étant donné que tu n'as pas précisé de valeur qui t'intéresse d'avantage).

    NOTA : l'un dans l'autre, tu aurais d'ailleurs sans doute largement intérêt à inverser l'ordre de ces termes, pour que KO soit égal à 0, pour une raison toute bête : la valeur booléenne false[est déinie comme état égale à 0 et la valeur booléenne true comme étant "tout ce qui n'est pas égal à false, pour permettre les conversions du genre de if(variableNumerique)). Mais bon, ce n'est encore qu'un détail

    Grâce à cela, chaque fois que le compilateur croisera le terme OK dans ton code, il le remplacera systématiquement par la valeur 0 et, chaque fois qu'il croisera le terme KO, il le remplacera systématiquement par la valeur 1.

    Mieux encore : la déclaration du type de donnée RESULTS se fait strictement en interne au niveau du compilateur, dans le sens où elle disparait totalement du code binaire qui sera généré : il ne restera plus que les valeur 1 et 0.

    Et le mieux de tout, c'est que le compilateur peut parfaitement utiliser ces valeurs 0 et 1 (associées respectivement aux termes OK et KO qu'il croise dans ton code) pour effectuer certains calculs et / ou certaines vérification dont seul le résultat final sera présent dans le code binaire.

    Evidemment, cela présente un inconvénient majeur par rapport aux classes et aux structures, dans le sens où tu ne peux pas te contenter d'indiquer au compilateur qui existe une énumération nommée RESULTS, car il doit systématiquement savoir quels sont les termes qui font partie de cette énumération, et à quelles valeurs ils sont associés

    En un mot comme en cent: il est impossible d'avoir recours à la déclaration anticipée avec les énumérations, et tu devras donc veiller à inclure le fichier d'en-têtes qui la décrit ... chaque fois que tu voudras utiliser une donnée de type RESULTS.

    Oui tout à fait.
    Néanmoins si beaucoup de classes ont des méthodes renvoyant ce type, alors dans par exemple ma fonction main, j'aurais plusieurs fois inclut ce même fichier "MyEnum.hpp". Même en utilisant le #ifndef pour éviter des redéclarations, cela peut faire beaucoup de fois le même fichier inclut dans un fichier .cpp.
    C'est justement à cela que servent les "garde anti inclusions multiples" (include guards en anglais): les pragma once et les autres
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    #ifndef UN_SYMBOLE_SPECIFIQUE
    #define UN_SYMBOLE_SPECIFIQUE
        /* le code du fichier d'en-tête vient ici */
    #endif
    C'est pour permettre au préprocesseur de se rendre compte que le contenu (ou qu'une partie du contenu) d'un fichier a déjà été ajouté, et donc de supprimer le contenu qui a été ajouté "une deuxième fois" (ou une deuxième, ou une cinquantième fois ).

    Mais, pour arriver à te faire comprendre le principe, il faudrait que je me lance dans une explication presque aussi longue que celle qui précède... je ferai peut-être cela "plus tard", si tu le souhaites, et uniquement si tu me le demandes
    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
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par MicBeastKiller Voir le message
    Mon fichier "main.cpp"
    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #include "MyEnum.hpp"
    #include "MyClass.hpp"
     
    int main( void )
    {
    // ....
    }
    De ce point de vue là oui tout à fait.
    D'où ma question initiale.
    As-tu envie que les gens incluent eux-mêmes "MyEnum.hpp" ? Tu as vu que si tu ne le fais, tu as des erreurs de compilation ? As-tu envie que les utilisateurs de ta classe se cassent la tête à trouver les headers à inclure ? Ou veux-tu leur simplifier la vie avec un MyClass.hpp auto-suffisant ?

  10. #10
    Membre régulier
    Inscrit en
    Juin 2008
    Messages
    140
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 140
    Points : 103
    Points
    103
    Par défaut
    Merci pour vos réponses très éclairantes.
    Je mets en résolu.

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

Discussions similaires

  1. inclusion aspx dans aspx
    Par alex61 dans le forum ASP.NET
    Réponses: 10
    Dernier message: 04/06/2010, 12h31
  2. inclusion script dans un fichier
    Par enzostar dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 10/11/2009, 09h59
  3. Inclusion VBScript dans ASP
    Par derzy971 dans le forum ASP
    Réponses: 4
    Dernier message: 17/06/2009, 23h51
  4. [HTML] Inclusion .jsp dans <div>
    Par vomilord dans le forum Balisage (X)HTML et validation W3C
    Réponses: 0
    Dernier message: 18/07/2008, 11h16
  5. Inclusion automatique dans une JSP
    Par Invité dans le forum Servlets/JSP
    Réponses: 3
    Dernier message: 07/05/2008, 09h11

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