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 : Passer du C au C++
(Article écrit par Randy Finch et extrait du Randy Finch's Web Site - février 1996)
|
|
Il y a plusieurs années, j'avais écrit un évaluateur de fonctions pour un programme de traçage de fonctions
en 3D. Il permettait à l'utilisateur de saisir une équation tridimensionnelle de la forme Z=F(X,Y) et de
calculer ensuite la valeur de Z pour toute combinaison de X et de Y. L'évaluateur de fonctions était écrit
en C. J'avais écrit un article à ce sujet pour ce magazine dans son
numéro d'octobre 1989.
Il y a plusieurs mois, j'ai réécrit l'évaluateur de fonctions en C++ à l'aide du SAS/C Development System
v6.50. J'ai trouvé que le code était beaucoup plus organisé et plus facile à lire et à modifier. À l'occasion,
je me référerai à l'article d'octobre 1989 en le comparant au nouveau code indiqué à la fin de cet article.
Aussi, si vous avez besoin de connaître plus de détails sur le fonctionnement de l'évaluateur de fonctions,
n'hésitez pas à lire l'ancien article. Donc, si vous en avez une copie, mettez-la à votre disposition pendant
que vous lisez cet article.
C vs. C++
Le C++ ajoute de nombreuses fonctionnalités au C. Certaines d'entre elles sont un contrôle de type plus
fort, l'orientation objet et l'héritage. Les deux premières étaient importantes pour mon programme. Une
vérification de type plus forte signifie simplement que C++ est plus pointilleux pour s'assurer que les
types de variables appropriés sont passés aux fonctions et que les variables sont utilisées dans un
programme comme elles sont déclarées. Comme vous le savez, le C était assez bon en matière de vérification
des types, mais pas aussi bon qu'il aurait pu l'être. J'ai été victime plusieurs fois à cause de ce laxisme.
La plupart des modifications apportées au code de l'évaluateur de fonctions, par opposition à sa structure,
visaient à satisfaire la vérification de type du traducteur C++. Si vous comparez le nouveau code avec l'ancien,
vous verrez de nombreux endroits où le type de conversion ("casting") est utilisé dans le code C++, mais pas
dans le code C.
L'orientation objet du code est la principale amélioration apportée à mon programme. Un programme C est
composé de données et de fonctions. De nombreux types de données différents sont disponibles et les structures
de données peuvent être déclarées comme des types de données personnalisés. En général, une fonction reçoit
une ou plusieurs variables, la fonction opère ensuite sur les variables et le contrôle est renvoyé au code
appelant. Dans un code complexe, cela peut entraîner une confusion lorsque des fonctions similaires, mais
différentes, sont utilisées pour opérer sur des données similaires, mais différentes.
Le C++ contourne ce problème en combinant les données et les fonctions en une seule entité appelée "objet".
La définition d'un objet s'appelle une "classe". Une classe C++ est très similaire à une structure de
données C. Elle contient des données, mais aussi des fonctions. Elle contient des données, mais aussi des
fonctions. Une fonction qui apparaît comme une partie d'un objet est appelée une "méthode". Ainsi, un
objet contient à la fois les données dont il a besoin et le code pour agir sur ces données, le tout en un
seul endroit. Si un programme doit demander à un objet de faire quelque chose, il appelle simplement l'une
des méthodes de l'objet. Un exemple typique est un programme graphique vectoriel qui permet de dessiner des
formes géométriques à l'écran. Chaque forme géométrique pourrait être un objet créé à partir d'une définition
de classe. Lorsqu'un objet réel est créé dans la mémoire de l'ordinateur à partir d'une définition de classe,
on parle d'instanciation, ou de création d'une instance de classe. L'objet peut contenir une méthode ChangeColor.
Si le nom de l'objet est GeoShape1, on peut utiliser quelque chose comme l'instruction suivante pour changer
sa couleur en rouge : GeoShape1.ChangeColor(RED).
En général, lors de la définition d'un objet en C++, deux fichiers sont créés : le fichier d'en-tête
(.hpp) et le fichier de code (.cpp). Le fichier d'en-tête, également appelé fichier de définition, contient
tous les #include, #define, les définitions de structure, etc. ainsi que la définition de la classe. Le
fichier de code, également appelé fichier d'implémentation, contient tout le code des méthodes. En séparant
le code de cette manière, tout programme qui a besoin d'utiliser un objet peut simplement inclure le fichier
d'en-tête et l'objet sera disponible pour lui. Il est recommandé que chaque objet ait son propre fichier
d'en-tête et de code. Cela permet de modifier un objet sans avoir à recompiler les autres objets.
FuncEval en C++
La version C++ de mon programme d'évaluation de fonctions définit une classe FuncEval qui contient toutes
les données et méthodes nécessaires à la création d'une fonction, au contrôle de la syntaxe, à l'obtention
d'informations sur les erreurs et à l'évaluation des valeurs X et Y. La fonctionnalité est la même que
dans l'ancien programme, mais elle est plus facile à comprendre et à modifier. Voyons cela.
Le listing 1
contient le fichier d'en-tête (FuncEval.hpp) pour l'objet FuncEval. Remarquez que toutes les
définitions d'erreurs syntaxiques ont été incorporées dans ce fichier. Elles étaient séparées dans la
version C. Les définitions de structure CharStackType et NumStackType sont les mêmes que les définitions
CharStack et NumStack du code C. Il est fortement recommandé, lors de la définition d'une structure, StructName,
que la structure soit nommée "StructNameType". Immédiatement après la définition, une instruction typedef
devrait être utilisée pour définir StructName comme une nouvelle variable de type StructNameType. C'est ce
que j'ai fait pour CharStack et NumStack.
La définition de classe réelle pour FuncEval apparaît à la fin du listing 1. Remarquez que les données et
les méthodes sont divisées en public et privé. Les données et méthodes publiques peuvent être utilisées
par un programme extérieur, alors que les données et méthodes privées ne le peuvent pas. Les données et
méthodes privées ne peuvent être utilisées que par les méthodes de l'objet. En général, il n'est pas recommandé
de rendre publiques les données, mais uniquement les méthodes. Si des données doivent être modifiées par un
programme, elles doivent l'être par une méthode publique. Dans l'exemple de l'objet forme géométrique, la
couleur a été modifiée par l'appel d'une méthode ; cependant, cela aurait pu être fait en rendant la variable
couleur publique et en laissant le programme exécuter l'instruction suivante : GeoShape1.Color=RED. En utilisant
une méthode pour modifier la couleur, de nouvelles fonctionnalités peuvent être ajoutées à l'objet sans qu'il
soit nécessaire de modifier le programme qui l'utilise. Pour la classe FuncEval, toutes les données et la plupart
des méthodes sont privées. Les méthodes publiques sont utilisées pour convertir une chaîne de fonction, obtenir
un numéro, un message et une position d'erreur, et évaluer la fonction pour des valeurs de X et Y. Lorsqu'une
méthode publique porte le même nom que la classe elle-même, elle est appelée un constructeur. Il s'agit d'une
méthode spéciale qui s'exécute chaque fois que la classe est instanciée. Le constructeur est utilisé pour
initialiser les variables et d'autres tâches qui doivent être effectuées avant l'utilisation de l'objet. Bien
que la classe FuncEval n'en ait pas, une classe peut également avoir un destructeur pour faire le ménage avant
la suppression d'un objet. Son nom est le même que celui du constructeur mais avec un tilde (~) devant (par
exemple, ~FuncEval).
Le fichier de code de FuncEval est présenté dans le
listing 2. Toutes les méthodes, à l'exception du constructeur
et de celles utilisées pour la gestion des erreurs, sont identiques à leurs fonctions équivalentes dans la
version C, à quelques exceptions près. Tout d'abord, la conversion de type est utilisé dans les méthodes pour
satisfaire la vérification de type plus forte du C++. Deuxièmement, les noms des méthodes sont différents des
noms des fonctions équivalentes. Si le nom de la fonction est CheckSyntax, sa méthode équivalente est nommée
FuncEval::CheckSyntax. Le préfixe "FuncEval::" associe une méthode à la classe FuncEval. D'autres objets peuvent
avoir une méthode avec le même nom. Quant au constructeur, il initialise simplement la position de l'erreur à 0.
Le listing 3
montre un programme, Main.cpp, qui utilise l'objet FuncEval pour évaluer une fonction 3D définie
par l'utilisateur. Ce programme est similaire au programme Testfevl.c de l'article d'octobre 1989. Cependant,
le code est quelque peu différent afin d'interagir correctement avec l'objet FuncEval. Au début de main() se
trouve l'instruction suivante :
FuncEval *func = new FuncEval
|
L'opérateur "new" instancie la classe "FuncEval", créant une instance réelle de l'objet FuncEval en
mémoire. Le pointeur vers cet objet est nommé "func". Le reste du programme est facile à suivre, mais
remarquez comment les méthodes publiques de FuncEval sont appelées : func->PublicMethodName. Le nom du
pointeur est utilisé car la méthode fait partie de l'objet.
~FuncEval
J'espère que vous avez apprécié cette courte introduction à la conversion de programmes C en C++.
Si vous voulez en savoir plus sur les différences entre C et C++, je vous recommande vivement le livre
indiqué ci-dessous. Si vous êtes déjà un programmeur C et que vous souhaitez passer au C++, vous ne pourrez pas
vous en passer :
Sessions, Roger ; Class Construction in C and C++ : Object-Oriented Programming Fundamentals ; PTR Prentice Hall, Inc ; 1992.
|