FAQ C++Consultez toutes les FAQ

Nombre d'auteurs : 35, nombre de questions : 368, dernière mise à jour : 17 novembre 2018  Ajouter une question

 

Cette FAQ a été réalisée à partir des questions fréquemment posées sur les forums de http://www.developpez.com et de l'expérience personnelle des auteurs.

Je tiens à souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose sont correctes ; les auteurs font le maximum, mais l'erreur est humaine. Cette FAQ ne prétend pas non plus être complète. Si vous trouvez une erreur ou si vous souhaitez devenir rédacteur, lisez ceci.

Sur ce, nous vous souhaitons une bonne lecture.


SommaireOrganisation du code source (7)
précédent sommaire suivant
 

Le strict minimum : c'est-à-dire les seuls fichiers d'en-tête contenant les déclarations ou définitions de ce qui va être utilisé et permettant ainsi à la compilation de réussir.

Mis à jour le 15 octobre 2009 3DArchi

Il est préférable d'avoir des déclarations anticipées (forward declaration) dans les fichiers d'en-tête et d'inclure l'en-tête de déclaration dans le fichier source. L'objectif à atteindre est que tout fichier d'en-tête doit pouvoir être inclus indépendamment des autres et compiler. Ce qui veut dire qu'un fichier d'en-tête doit contenir le moins de choses possibles.

Code c++ : Sélectionner tout
1
2
3
4
class A 
{ 
    // déclaration de la classe A 
};
Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
class A; // déclaration anticipée 
class B 
{ 
    // déclaration de la classe B 
    // … 
  
   void do_someting_with_a_A(A const &); 
};
Code c++ : Sélectionner tout
1
2
3
#include "B.h" 
#include "A.h" 
// définition de B…
À noter que la déclaration anticipée n'est possible que si le compilateur n'a pas besoin de connaître complètement le type : pointeur, référence. On ne peut l'utiliser ni pour l'héritage ni pour la composition.
Pour aller plus loin avec les déclarations anticipées, jusqu'à présent vous avez l'habitude de découper votre code en deux fichiers : un fichier d'en-tête MyClass.h pour la déclaration et un fichier d'implémentation MyClass.cpp pour la définition. Notez qu'on peut associer un troisième fichier MyClassFwd.h pour regrouper les déclarations anticipées liées à CMyClass. Ce fichier contient tout naturellement une déclaration anticipée de la classe :

Code c++ : Sélectionner tout
class CMyClass;
Mais, c'est l'occasion d'y mettre aussi d'autres déclarations associées qui vont systématiquement (ou presque) avec votre classe. Ce peut être des enum, des déclarations de fonctions externes, etc. :

Code c++ : Sélectionner tout
1
2
3
4
5
6
class CMyClass; 
enum E_options_my_class 
{ 
   // … 
}; 
std::ostream& operator << (std::ostream& O, const CMyClass& B);
Lorsqu'une autre classe nécessite une déclaration anticipée de CMyClass, elle fait alors appel à cet en-tête :

Code c++ : Sélectionner tout
#include "MyClassFwd.h"

Mis à jour le 15 octobre 2009 3DArchi

  1. Le fichier d'en-tête de la déclaration de la classe ;
  2. les fichiers standards (STL) ;
  3. les fichiers d'en-tête de l'O.S. ;
  4. les fichiers d'en-tête des bibliothèques tierces (boost, xml, wxWidget…) ;
  5. les fichiers d'en-tête de mes bibliothèques externes ;
  6. les fichiers d'en-tête de mon projet.

Cet ordre est une proposition parmi d'autres qui ont aussi leur légitimité. Vous pouvez suivre un autre ordre d'inclusion si vous en sentez le besoin compte tenu de vos pratiques habituelles ou du contexte de votre application. En fait, l'idée maîtresse est de maintenir une cohérence sur l'ensemble du projet. Quelle que soit la politique que vous choisissez de mettre en ouvre, utilisez la même systématiquement dans tous vos fichiers.

Mis à jour le 15 octobre 2009 3DArchi Luc Hermitte

Une classe est déclarée dans un fichier header (extension .h, .hpp. ou encore .hxx) dont l'inclusion multiple est protégée grâce à des directives du préprocesseur :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
#ifndef MACLASSE_H 
#define MACLASSE_H 
  
class MaClasse 
{ 
public: 
    void Fonction(); 
}; 
  
#endif
Le corps de la classe est généralement placé dans un fichier séparé dont l'extension varie (.cpp, .cxx, .C). Ce fichier contient le code compilable :

Code c++ : Sélectionner tout
1
2
3
4
5
6
#include "maclasse.h" 
  
void MaClasse::Fonction() 
{ 
    // implémentation de la fonction 
}
Pour utiliser une classe dans d'autres fichiers .cpp, il suffira d'inclure l'en-tête qui la déclare ; c'est l'éditeur de liens qui se chargera de trouver tout seul où se trouve le corps des fonctions (i.e. vous n'avez pas à vous en préoccuper).
Certains seront parfois tentés d'inclure un fichier .cpp : c'est une erreur et cela ne doit jamais être fait (il en résulterait plusieurs corps pour une même fonction, par exemple).

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
#include "autreclasse.h" 
#include "maclasse.h" 
  
void AutreClasse::Fonction() 
{ 
    MaClasse M; 
    M.Fonction(); 
}
Le corps de certaines fonctions peut figurer dans le header, en particulier pour les fonctions inline et dans le cas de fonctions/classes templates (lire à ce sujet Pourquoi mes templates ne sont-ils pas reconnus à l'édition des liens ?). Attention à ne pas oublier le mot clé inline si vous placez le corps de fonctions dans un header ailleurs que dans la déclaration d'une classe :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#ifndef MACLASSE_H 
#define MACLASSE_H 
  
class MaClasse 
{ 
public: 
    void FonctionInline() 
    { 
        // Placée dans la déclaration de la classe 
        // cette fonction est considérée en ligne sans 
        // que le mot clé inline ne figure 
    } 
}; 
  
// Placée en dehors de la déclaration de la classe, le mot clé inline 
// est indispensable pour ne pas provoquer des définitions multiples 
// de la fonction et donc des erreurs à l'édition de liens 
inline void FonctionInline2() 
{ 
} 
#endif
Soyez aussi vigilants au respect de la casse dans l'inclusion d'une header. Si vous incluez maclasse.h, veillez à bien nommer votre fichier header maclasse.h et non MaClasse.h car certains systèmes font la distinction de casse dans le nom des fichiers et cela s'applique aussi lors de leur inclusion dans un fichier C++.

Mis à jour le 3 février 2007 Aurelien.Regat-Barrel Laurent Gomila

Les templates nécessitent d'avoir toute la définition dans le fichier d'en-tête. Pour maintenir une politique cohérente, on peut séparer la déclaration d'une classe template (.h) et sa définition (.tpp). La définition est incluse à la fin du fichier de déclaration :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
template<class T> 
class TMyTemplateClass 
{ 
public:  
   void do_something(); 
}; 
#include "MyTemplateClass.tpp"
Code c++ : Sélectionner tout
1
2
3
4
5
6
7
// en-tête si besoin 
  
// définition 
template<class T> 
void TMyTemplateClass<T>::do_something() 
{ 
}

Mis à jour le 15 octobre 2009 3DArchi

Inclure le fichier en tout premier dans un fichier .cpp. Ce dernier doit compiler sans erreur.

Mis à jour le 15 octobre 2009 3DArchi JolyLoic

Les en-têtes précompilés n'offrent malheureusement pas de standard dans leur mise en ouvre. Tous les compilateurs ne les supportent pas, et ceux qui savent les gérer ne le font pas tous de la même façon. Est-ce une raison pour les abandonner ? Non. Car ils offrent de vrais avantages en terme de temps de compilation, surtout pour les projets utilisant des bibliothèques volumineuses ou complexes. La question qui se pose alors est de savoir quoi mettre dans les en-têtes précompilés ? Il faut garder à l'esprit l'objectif des en-têtes précompilés : accélérer la compilation. Il faut donc veiller à mettre les fichiers des bibliothèques externes récurrents dans vos sources ainsi que ceux qui sont susceptibles de provoquer des inclusions en cascade (afxXXX.h avec les MFC, wx.h dans wxWidgets). En revanche ne mettez pas des fichiers d'en-têtes du projet en cours car ce sont ceux qui sont le plus susceptibles de varier et dégradent ainsi le temps de compilation en forçant à tout recompiler.
Il faut être vigilant à ne pas transformer le fichier d'en-têtes précompilés en un fourre-tout contenant tous les fichiers de toutes les bibliothèques utilisées dans un projet. Cela rompt le principe qui veut que l'on minimise les dépendances entre les unités de compilation. Identifiez correctement les fichiers clés qui sont significatifs dans le temps de compilation de votre projet.

Mis à jour le 15 octobre 2009 3DArchi

Proposer une nouvelle réponse sur la FAQ

Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2019 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

 
Contacter le responsable de la rubrique C++

Partenaire : Hébergement Web