|

Écrivez
à AILES ! |

Retour
vers programmation |

Retour
vers les questions C++ |

C'est quoi, un "paradigme"
? |
|
|
Questionnaire C++
Multi-Paradigmatique
[BjarneStroustrup]
|
Voici toutes les réponses! |
En quoi le C++
est-il "multi-paradigmatique"
Il est multi-paradigmatique car il permet une
programmation basé sur les paradigmes :
- objet et
- générique (les templates) ;
Au sujet du seul paradigme orienté objet,
Stroustrup fait remarquer dans son interview donnée au IEEE (cf. [BjarneStroustrup]) que :
« Définir OO comme étant basé sur l'utilisation d'une hiérarchie
de classe et de fonctions virtuelles est pratique car cela fournit des
indications quant aux domaines où l'OO a des chances d'être
efficace. Vous cherchez :
- des concepts qui supportent un ordonnancement hiérarchique ;
- des variantes de concepts qui peuvent partager une même
implémentation et
- des objets qui peuvent être manipulés au travers d'une même
interface sans être exactement du même type.
Avec quelques exemples et un peu d'expérience, cela peut devenir la
base d'une approche très efficace de conception.
Toutefois, tous les concepts ne supportent
pas utilement la notion de hiérarchie, les relations entre les
concepts ne sont pas tous de nature hiérarchique et tous les
problèmes ne sont pas abordés avec "l'objet" comme premier
référent. Par exemple, certains problème sont avant tout de
nature algorithmique. En conséquence, un langage de programmation aux
objectifs généraux supporte une large gamme de style de
programmation. »
Dans sa FAQ (cf.
[BjarneStroustrup]), il ajoute :
« Multi-paradigme est une façon élaborée de dire "programmer
en utilisant plus qu'un style de programmation, chacun à bon
escient". Par exemple, utiliser la programmation orientée-objet
là où l'identification des différents types d'objet pendant
l'exécution est importante, et utiliser la programmation générique
là où le contrôle du type à la compilation et où les performances
à l'exécution sont recherchées.»
Il ajoute que la force de cette approche est de
pouvoir mêler les deux paradigmes, comme dans cet
exemple :
//
draw each element of a standard vector
void draw_all(vector< Shape*>& vs)
{
for_each(vs.begin(),vs.end(),mem_fun(&Shape::draw));
} |
Ici, Shape est une classe abstraite
définissant l'interface d'une hiérarchie de formes
géométriques. Cet exemple se généralise facilement à tout
type de container. |
// draw each element
of a standard container
template< class C> void draw_all(C& cs)
{
for_each(cs.begin(),cs.end(),mem_fun(&Shape::draw));
} |
Attention, comme le souligne, en
C++, les types génériques sont non contraints. Au sein d'une entité
paramétrée par un tel type, n'importe quelle opération est
applicable aux entités de ce type; la vérification sémantique de la
validité de l'opération doit être faite pour chaque instanciation
spécifique. Mieux vaut donc passer un "Shape" qui supporte
"draw", surtout que mem_fun (décrit par Rogue
Wave ou SGI)
se contente d'appeler la fonction draw à l'adresse de l'objet + le
décalage correspondant à la fonction draw, issu de la table de
pointeurs des fonctions virtuelles. (cf. héritage multiple et représentation en mémoire).
Seul Eiffel peut contraindre un type générique à
respecter une interface donnée (généricité contrainte) :
deferred class Comparable
feature
infix "<" (other: like Current): Boolean is
deferred
end;--infix "<"
infix ">" (other: like Current): Boolean is
deferred
end;--infix ">"
[... etc]
end;--class Comparable;
class Liste_Triee[Element->Comparable]
placer(x: Element)is
local
curseur: Noeud[Element];
do
if tete=Void or else x<=tete.valeur then
!!tete.creer(x,tete)
else
from curseur:=tete
until curseur.suivant=Void
or else
x<=curseur.suivant.valeur
loop
curseur:=curseur.suivant
end;
curseur.suivre(x)
end;
longueur:=longueur+1
end;--placer
end;--class Liste_triee
|