Suivez-nous sur X

|
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
ALL
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
A propos d'Obligement
|
|
David Brunet
|
|
|
|
Programmation : Principes de base de la programmation objet
(Article écrit par Onlytoine et extrait de GuruMed.net - janvier 2003)
|
|
1. Introduction
Ceci est un article visant à démystifier la programmation objet qui demande une approche différente de
celle que l'on observe généralement avec les langages procéduraux. Afin d'illustrer les principes exposés,
le langage C++ sera utilisé : c'est l'un des plus communs avec Java et c'est le plus accessible et le
plus connu sur Amiga.
2. Pourquoi programmer objet ?
Programmer objet, c'est identifier et définir des entités, formées d'un ensemble cohérent de données
sur lesquelles on peut effectuer un certain nombre d'opérations. Les données sont d'ailleurs encapsulées
de telle manière qu'il est très facile de les protéger efficacement : un objet est une boîte et on s'adresse
à la boîte pour manipuler des données qu'elle contient.
Cette programmation permet de rendre le code plus facilement modulaire et réutilisable car chaque entité
a été créée pour répondre à un problème et apporter ses solutions. Un tel découpage en modules est bien
sûr possible avec le langage C par exemple mais les langages objet offrent pour la plupart des mécanismes
puissants que l'on abordera par la suite : héritage, copie d'objets, surcharge, exceptions, etc.
On peut donc programmer de façon modulaire en C et quelqu'un qui maîtrise déjà parfaitement le langage C
et ne ressentira pas forcément le besoin d'autre chose, d'autant que le C++ est plus riche et demandera
donc des efforts d'apprentissage supplémentaires.
Par ce qu'ils apportent de plus, les langages objet imposent d'accepter une certaine rupture avec ses
habitudes et l'image qu'on se fait des langages objet qui ne sont pas qu'une couche supplémentaire du C.
3. Définition d'une classe
Les langages objet offrent des fonctionnalités permettant une programmation simple et robuste. Au centre
de ces possibilités : la classe. Chaque objet (cette boîte dont nous parlions) est créé à partir de la
description d'une classe.
Une classe est une structure de données à laquelle on ajoute des fonctions qui lui sont propres et qui
lui permettent de gérer ses données.
Mais outre l'ajout de ces fonctions, il existe deux grandes nouveautés par rapport aux structures du C :
- D'une part, les membres de classe, qu'ils soient des propriétés ou des fonctions, peuvent être
privés, c'est-à-dire inaccessibles de l'extérieur (alors que tous les éléments d'une structure du C
étaient accessibles).
- D'autre part, une classe peut être dérivée. La classe dérivée hérite alors de toutes les propriétés
et fonctions de la classe mère.
4. Autopsie d'une classe
Voilà une classe C++ très simple qui est commentée juste après. Attention, afin de ne pas surcharger le
code, on a omis quelques vérifications qui seraient indispensables dans une utilisation réelle de
l'exemple. En effet, on ne vérifie ni le signe de l'âge ni la taille du nom. D'autre part, on utilise
un tableau de caractères pour le nom mais on aurait pu exploiter avantageusement la classe "string".
class Personne {
private:
char firstname[256];
int age;
public:
Personne(char *firstname, int age) {
if (firstname != NULL){
strncpy(this->firstname, firstname, 255);
}else{
this->firstname[0] = '\0';
}
this->age = age;
}
~Personne() {}
char * getFirstName() {
return this->firstname;
}
int getAge() {
return this->age;
}
void setFirstName(char* firstname) {
if(firstname != NULL) {
strncpy(this->firstname, firstname, 255);
}
}
void setAge(int age) {
this->age = age;
}
};
|
Les mots-clés "private" et "public" définissent cette fameuse visibilité des données et fonctions
qui les suivent. Dans notre exemple, les données "firstname" et "age" sont privées : elles sont
inaccessibles hors de la classe. Quant aux quatre fonctions, elles sont publiques, elles peuvent
être appelées sans restriction, entre elles ou depuis l'extérieur.
Note : si vous tentez d'accéder à des données ou des fonctions privées depuis l'extérieur, le
compilateur va vous faire de gros yeux et vous demander gentiment de modifier votre code. :o)
Vocabulaire : les données dans une classe sont appelées "attributs" de la classe ; les fonctions sont
appelées "méthodes" de la classe.
Les deux méthodes bizarres qui ne renvoient aucune valeur sont :
- "Personne() {}" : le constructeur.
- "~Personne() {}" : le destructeur.
Le constructeur est une méthode qui est appelée lors de l'instanciation d'un objet : c'est-à-dire la
création d'un espace en mémoire pour cet objet (comme "malloc()" en C). On s'en sert donc pour créer
(allouer) l'objet mais aussi pour l'initialiser éventuellement.
Le destructeur est la méthode appelée lorsque l'instance doit être détruite (comme "free()" en C). Nous y
reviendrons plus tard.
5. Utilisation d'une classe dans un programme
Voilà comment utiliser notre classe "Personne" au sein d'un programme :
#include <stdio.h>
#include <string.h>
#include "Personne.h"
int main(int argc, char *argv[])
{
Personne stan("StAn", 26);
Personne poly("Poly", 28);
printf("%s %d\n", stan.getFirstName(), stan.getAge());
printf("%s %d\n", poly.getFirstName(), poly.getAge());
stan.setFirstName("Olive");
stan.setAge(10);
poly.setFirstName("Tom");
poly.setAge(stan.getAge()+1);
printf("%s %d\n", stan.getFirstName(), stan.getAge());
printf("%s %d\n", poly.getFirstName(), poly.getAge());
return 0;
}
|
6. Le vif du sujet
Pour illustrer cette introduction, prenons l'exemple connu des formes géométriques qui va vous montrer
l'utilité du C++ dans la programmation objet.
Alors voilà, un beau matin, vous vous dîtes : "Tiens, j'aurais besoin d'une structure de données
correspondant à un Rectangle !" (si c'est le cas, faîtes attention à votre santé). Vous décidez
pour une fois d'épargner votre compilo C et d'écrire une petite classe en C++ répondant à vos exigences.
class Rectangle {
// ...
};
|
Bon début, n'est-ce pas ? Un rectangle à une origine (x,y), une largeur, une hauteur... Voilà pour les données.
class Rectangle {
// *** Attributes ***
private:
int x, y;
int width, height;
// ...
};
|
Il est de bonne habitude de déclarer les données privées et d'écrire des "Getter" pour y accéder et
des "Setter" pour les modifier. On appelle plus communément ces fonctions des "accesseurs".
class Rectangle {
// *** Attributes ***
// ...
// *** Getters ***
public:
int getX() { return this->x; };
int getY() { return this->y; };
int getWidth() { return this->width; };
int getHeight() { return this->height; };
// *** Setters ***
public:
void setX(int x) { this->x = x; };
void setY(int y) { this->y = y; };
void setWidth(int w) { this->width = w; };
void setHeight(int h) { this->height = h; };
};
|
A présent, il nous faut pouvoir construire une instance de cet objet (avec le mot-clé "new"). Il
est possible de définir plusieurs constructeurs. Il faut également penser au destructeur appelé
lors de l'appel de la fonction "delete()".
class Rectangle {
// *** Attributes ***
// ...
// *** Constructor/Destructor ***
public:
Rectangle(int x=0, int y=0, int w=100, int h=100) {
this->setX(x);
this->setY(y);
this->setWidth(w);
this->setHeight(h);
};
~Rectangle() {
// Rien à faire
};
// *** Getters ***
// ...
// *** Setters ***
// ...
};
|
Notez la présence du constructeur sans paramètre, qui effectue en interne un appel au constructeur
avec paramètre en lui fournissant des valeurs par défaut (mais on ne contrôle pas la validité de
ces valeurs, il y a donc un risque). Le destructeur n'a rien à faire dans notre exemple car nous
n'avons rien alloué (données ou ressource) dans cet objet.
Pour les opérations utiles sur un Rectangle : obtenir le périmètre, obtenir l'aire. On va s'arrêter
là pour l'instant.
class Rectangle {
// *** Attributes ***
private:
int x, y;
int width, height;
// *** Constructor/Destructor ***
public:
Rectangle(int x=0, int y=0, int w=100, int h=100) {
this->setX(x);
this->setY(y);
this->setWidth(w);
this->setHeight(h);
};
~Rectangle() {
// Rien à faire
};
// *** Getters ***
public:
int getX() { return this->x; };
int getY() { return this->y; };
int getWidth() { return this->width; };
int getHeight() { return this->height; };
// *** Setters ***
public:
void setX(int x) { this->x = x; };
void setY(int y) { this->y = y; };
void setWidth(int w) { this->width = w; };
void setHeight(int h) { this->height = h; };
// *** Business' Methods ***
public:
int getPerimeter() {
return this->width*2 + this->height*2;
};
int getArea() {
return this->width * this->height;
};
};
|
Voilà un exemple de programme de test :
#include <stdio.h>
#include "Rectangle.h"
int main(int argc, char *argv[])
{
Rectangle rect(10, 15, 200, 300);
printf("x : %d\n", rect.getX());
printf("y : %d\n", rect.getY());
printf("Largeur : %d\n", rect.getWidth());
printf("Hauteur : %d\n", rect.getHeight());
printf("Périmètre : %d\n", rect.getPerimeter());
printf("Aire : %d\n", rect.getArea());
return 0;
}
|
Résultat de l'exécution :
- >> TestRectangle
- x : 10
- y : 15
- Largeur : 200
- Hauteur : 300
- Périmètre : 1000
- Aire : 60000
7. Fin de l'aperçu
Nous avons donc, à travers ces exemples, découvert comment écrire une classe C++ et comment l'utiliser.
J'entends déjà les fervents défenseurs du C qui se disent que tout ce qui a été exposé ici peut être
écrit également en C. Ma réponse : oui. :o)
Cependant, vous noterez déjà des possibilités intéressantes du C++ : l'objet dispose de ses propres données
et méthodes qui peuvent être privées ou publiques. L'instanciation et la destruction d'un objet se font
par l'intermédiaire de "new" et "delete".
Dans le prochain
article, nous verrons d'autres possibilités vraiment intéressantes du C++ comme l'héritage,
le polymorphisme ou encore la gestion des exceptions... Que de mots barbares pour décrire des fonctionnalités
qui facilitent vraiment la vie du programmeur et rendent le code concis, robuste et réutilisable.
|