Blog ENI : Toute la veille numérique !
🐠 -25€ dès 75€ 
+ 7 jours d'accès à la Bibliothèque Numérique ENI. Cliquez ici
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
  1. Livres et vidéos
  2. C++
  3. Des programmes C++ efficaces
Extrait - C++ Des fondamentaux du langage aux applications (3e édition)
Extraits du livre
C++ Des fondamentaux du langage aux applications (3e édition) Revenir à la page d'achat du livre

Des programmes C++ efficaces

Dépasser ses programmes

1. Oublier les réflexes du langage C

Les programmeurs habitués au langage C ont sans doute prévu de nombreuses macros instructions traitées par le préprocesseur. C’est notamment le cas des constantes textuelles et de "fonctions" qui rendent bien des services.

Le langage C++ propose cependant des alternatives qui améliorent la sûreté du programme ainsi que sa rapidité.

Les constantes définies avec le mot-clé const, tout d’abord, présentent l’énorme avantage d’être vérifiées par le compilateur et non par le préprocesseur. En cas d’erreur - visibilité, orthographe... - le compilateur peut donner beaucoup plus de contexte au programmeur.

Les fonctions en ligne (inline) permettent de développer des instructions sans construire tout un cadre de pile, avec les conséquences que cela peut avoir sur la transmission des arguments et sur les performances. Naturellement, leur mise en œuvre doit satisfaire à quelques contraintes mais il y a des bénéfices certains à les employer.

Considérons l’exemple suivant, dans lequel une constante symbolique est définie à l’attention du préprocesseur. En cas d’erreur d’écriture dans le main, le compilateur n’a aucun moyen de préciser dans quel fichier .h elle pourrait ne pas correspondre. De même, nous avons décrit au chapitre De C à C++ une macro qui compare deux entiers. Mais s’agissant d’une macro qui répète l’un de ses arguments, nous constatons que des effets de bord apparaissent.

L’exemple suivant propose une alternative à chaque problème, basée sur la syntaxe C++ plus sûre et plus rapide :

#define TAILLE 10 
#define COMP(a,b) (a-b>0?1:(a-b==0?0:-1)) 
 
const int taille = 10; 
inline int comp(int a,int b) 
{ 
    if(a-b>0) 
        return 1; 
    else 
    { 
    ...

La conception orientée objet (COO)

1. Relation entre la POO et la COO

La conception d’un programme orienté objet en C++ est une étape qui demande une certaine maturation. L’essence d’un tel programme ne tient pas seulement à l’implémentation des algorithmes qu’il contient, mais bien à la structure des classes et aux relations qui les réunissent. Nous nous proposons dans cette section de décrire les approches de méthodes liées à la conception de programme C++.

a. L’approche initiale de C++

Avant tout, rappelons-nous que C++ a été créé pour réaliser des applications à destination du domaine des télécommunications. Ce langage n’est donc pas seulement un travail de recherche, mais c’est aussi le fruit d’un travail d’ingénierie informatique. Bien entendu, son concepteur Bjarne Stroustrup s’est assuré qu’il était suffisamment général pour être adapté à d’autres situations. Pour atteindre cet objectif, il a conçu trois éléments essentiels :

  • le langage C++ en lui-même ;

  • la bibliothèque standard STL ;

  • une méthode de conception orientée objet pour C++.

La méthode proposée par Bjarne Stroustrup repose évidemment sur son expérience de conception d’applications antérieure à C++. Elle se fonde sur un certain nombre de thèmes forts, dont certains sont des classiques des méthodes de conception logicielle, orientée objet ou pas. Citons parmi ces thèmes la délimitation du système, la complexité des applications par rapport au degré d’abstraction des outils, ou encore les cycles de conception et de programmation perçus comme des activités itératives.

Le processus de développement minimal est constitué de trois étapes :

  • analyse ;

  • conception ;

  • implémentation.

L’étape qui nous préoccupe est justement celle de la conception. L’auteur de la méthode organise des sous-processus à partir du découpage suivant :

  • identification des classes, des concepts et de leurs relations les plus fondamentales ;

  • spécification des opérations...

Travaux pratiques

Sans être une fin en soi, les designs patterns guident le développeur dans la mise au point de son programme en lui évitant de réinventer la roue. L’exemple qui suit illustre le principe de séparation du code par niveau de préoccupation (on parle de "couches" de code) et s’appuie sur le design pattern Fabrique (Factory).

1. L’objectif du programme

Une classe de donnée assez simple, Livre contient deux attributs auteur et titre.

Le programme comporte une classe de service afin de lister des livres à partir de différentes sources (appelées DAO pour data access object) telles qu’une base de données, un fichier ou bien une sélection prédéfinie (autrement dit une liste codée en dur).

La fonction main() réalise deux appels à la classe de service, le premier pour lister tous les livres du catalogue, le second pour lister les ouvrages filtrés par auteur.

2. Le diagramme de classes

Certaines classes sont assorties d’une classe d’interface qui définit le contrat fonctionnel au travers d’une liste de méthodes virtuelles pures (aussi appelées méthodes abstraites en C# ou en Java).

Cette construction est assez classique dans le découpage d’un programme en couches, et elle est d’autant plus utile que le design pattern Factory entre en jeu.

images/06NEWRI01.png

Les classes d’interfaces sont représentées comme des classes abstraites puisque leurs méthodes ne comprennent pas d’implémentations (ce sont des méthodes virtuelles pures).

En C++, voici comment s’écrit cette association classe d’interface - classe :

/* 
   classe d'interface IlivreDAO 
   Ne contient que des méthodes virtuelles pures (sans code) 
 ...