19 janv. 2012

Presentation C++

Ce semestre nous avons eu un module de C++. Trois cours censé nous donner les bases du langage, en faisant un tour d'horizon de ses particularités. Il faut savoir que le C++ n'est pas un langage facile, par exemple la construction des objets peut être implicite, il faut s'occuper de beaucoup de mécanismes qu'on prend pourtant comme acquis en Java. Nous avons pris l'habitude avec notre prof de séparer la spécification de l'implémentation. Je ne reviendrais pas sur le paradigme orienté objet car ce n'est pas le but de cet article.


Un peu d'histoire

Vers la fin des années 70, un certain Bjarne Stroustrup décide d'enrichir le langage C dans les labos d'AT&T. Il souhaite ajouter le concept de classes afin de pouvoir rendre plus puissant le langage C. Une première version du langage sort, C with classes, inspiré de Simula 67. C'est principalement un ensemble de macro rajouté à C, les classes n'étant que du sucre syntaxique évalué et remplacé par du vrai code C par le préprocesseur. Finalement au milieu des années 80, des améliorations sont apportées, et c'est véritablement le code tapé qui est compilé, ainsi est né C++. Depuis les années 90, un processus de normalisation s'attelle à standardiser le langage, mais aussi la librairie l'accompagnant (Standard Template Library). Au final plusieurs extensions lui sont greffées, car jugés nécessaires, en contre partie ça a beaucoup complexifié le langage.

STL

Ou Standard Template Library, est un ensemble de fonctions classes qui sont des utilitaires, entre autre il y a des vecteurs, des piles, en fait les structures de données usuelles qu'on n'aura pas à réécrire nous même. Attention la STL n'est pas l'équivalent en Java des packages que l'API fourni gracieusement ! Loin de là, à par <string>, on à pas vraiment de quoi enrichir les objets de base.

Boost

Boost est une librairie qui en gros va ajouter une couche d'abstraction entre du C++ de bas niveau et des fonctions d'ordre supérieur. On bénéficie ainsi d'un for-each, de wrappers pour certains algorithmes (comme le minmax par exemple), la création et l'utilisation de sockets, ou encore une simplification de la gestion des threads.

C++

Une spécification de classe C++ (le .h) s'écrit de la manière suivante:
 1:  class Bebete: public QObject {
 2:  public:
 3:    Bebete (int posx,
 4:            int posy,
 5:            int posdx,
 6:            int posdy) : x(posx),
 7:                         y(posy),
 8:                         dx(posdx),
 9:                         dy(posdy) { }
10:    int X () const;
11:    int Y () const;
12:    int Dx () const;
13:    int Dy () const;
14:    void setX (int);
15:    void setY (int);
16:    void setDx (int);
17:    void setDy (int);
18:  
19:  private:
20:    int x,y,dx,dy;
21:  };
Cette classe représente une Bebete qui hérite de la classe QObject (pour info QObject est une classe de Qt, utilisée dans de l'interfaçage graphique). C++ permet l'héritage multiple qui du point de vue sémantique pose de gros problèmes, de plus nous ne possédons pas le concept d'interface (Java) ou protocol (Objective-C), qui permet de faire la différence entre l'héritage de type, et l'héritage d'un comportement. Vous trouverez peut être bizarre le constructeur de Bebete, qui possède entre la partie des paramètres et le corps de la méthode une zone particulière qu'on appelle la préséance. La préséance est exécutée après l'instanciation des attributs de la classe (et des parents) et avant l'execution du corps de la méthode. Maintenant l'implémentation (le .cc ou .cpp):
include "Bebete.h"

Bebete::X () {
  return this->x;
}
Bebete::Y () {
  return y;
}
Bebete::Dx () {
  return this->dx;
}
Bebete::Dy () {
  return dy;
}
Bebete::setX (int x) {
  this->x = x;
}
Bebete::setY (int newY) {
  y = newY;
}
On remarque qu'il faut précéder le nom de la méthode par le nom de la classe appartenante. Le mot clé this permet à l'instar de Java d'avoir une référence vers l'instance courante. Par contre il n'existe pas en C++ de mot clé super, ce qui serrait ambigüe car on peut potentiellement avoir plusieurs parents. En C++ si on veut accéder à un parent, on l'appelle directement par son nom de classe. A la différence de Java ou on distingue la déclaration de l'instanciation, en C++ la déclaration implique l'instanciation, donc si je pose la déclaration suivante:
Bebete maBebete;
revient au même que:
Bebete maBebete();
on appelle ici le constructeur par défaut, que l'on à pas écrit nous même, et qui est donné par le compilateur. maBebete ici est bien l'instance de Bebete qu'on vient de créer, ça veut dire qu'on a alloué quelque part de la mémoire pour cette instance. A la fin de la méthode, cette instance serra libérée automatiquement. Par contre si on instancie un objet comme en Java:
Bebete *maBebete = new Bebete();
Je manipule mon objet par pointeur, et il est de ma responsabilité de le détruire à la fin de son utilisation, grâce au destructeur qui est lui aussi fourni par le compilateur. J'espère que j'ai été assez clair, de toute manière une suite d'articles est en cours sur C++ :)

Aucun commentaire: