OVH Cloud OVH Cloud

La fin de l'héritage ?

103 réponses
Avatar
Olivier Azeau
J'ai lu avec grand intérêt l'article "Concepts for C++0x" mentionné dans
un thread récent.
Habituellement, je ne m'intéresse pas aux évolutions du langage car
elles ne me concernent qu'à un relativement long terme, mais là, j'ai
l'impression qu'un mouvement de fond relatif aux paradygmes du C++ prend
une certaine ampleur.
Et ce mouvement m'amène à quelques interrogations.

La plupart des développeurs que je cotoie programment en C++ dans un
style orienté objet très proche de ce que l'on trouve en Java.

Je prends un exemple classique de Bridge+Factory pour illustrer mon propos.
On a typiquement une hiérarchie d'implémentations :
| class DocumentDisplay {
| virtual ~DocumentDisplay();
| virtual void drawText( int x, int y, std::string const &text ) = 0;
| virtual void drawLine( int x1, int y1, int x2, int y2 ) = 0;
| };
|
| class GraphicDocumentDisplay : public DocumentDisplay {
| virtual void drawText( int x, int y, std::string const &text );
| virtual void drawLine( int x1, int y1, int x2, int y2 );
| };
|
| class TextDocumentDisplay : public DocumentDisplay {
| ...

une hiérarchie d'abstractions qui utilisent les implémentations :
|
| class Document {
| public:
| Document( DocumentDisplay *display ) : display_(display) {}
| virtual ~Document();
|
| void drawFrame( int x, int y, int w, int h, std::string const &title ) {
| display_->drawLine( x, y, x+w, y );
| display_->drawLine( x, y+h, x+w, y+h );
| display_->drawText( x, y, title );
| }
| private:
| DocumentDisplay *display_;
| };
|
| class Memo : public Document {
| public:
| Memo( DocumentDisplay *display ) : Document(display) {}
| void drawSummary() { drawFrame( 0, 0, 150, 100, "Summary" ); }
| };
|
| class Invoice : public Document {
| ...

une hiérarchie de fabriques pour instancier tout ça :
| class DocumentFactory {
| public:
| virtual ~DocumentFactory() {}
| virtual Memo *createMemo() = 0;
| virtual Invoice *createInvoice() = 0;
| };
|
| class GraphicDocumentFactory : public DocumentFactory {
| public:
| virtual Memo *createMemo() { return new Memo( new
GraphicDocumentDisplay ); }
| virtual Invoice *createInvoice() { return new Invoice( new
GraphicDocumentDisplay ); }
| };

et je rajoute un programme principal pour utiliser le tout :
| class Application {
| public:
| Application( DocumentFactory *factory ) : factory_(factory) {}
|
| void run() {
| Memo *memo = factory_->createMemo();
| memo->drawSummary();
| }
| private:
| DocumentFactory *factory_;
| };
|
| int main() {
| Application app( new GraphicDocumentFactory );
| app.run();
| }

En pratique, ça a une tête un peu différente (avec le RAII par exemple),
mais l'idée des hiérarchie de classes est là.

Depuis quelques temps se répand la programmation générique qui permet de
faire la même chose avec (en général) moins de lignes de code.

Les implémentations deviennent des "policy" et n'ont plus besoin de
classe de base
| class GraphicDocumentDisplay {
| virtual void drawText( int x, int y, std::string const &text );
| virtual void drawLine( int x1, int y1, int x2, int y2 );
| };

Les abstractions sont paramétrées par la policy.
On garde un héritage pour partager l'implémentation :
| template <class DOCDISP>
| class Document {
| public:
| virtual ~Document() {}
|
| void drawFrame( int x, int y, int w, int h, std::string const &title ) {
| display_.drawLine( x, y, x+w, y );
| display_.drawLine( x, y+h, x+w, y+h );
| display_.drawText( x, y, title );
| }
| private:
| DOCDISP display_;
| };
|
| template <class DOCDISP>
| class Memo : public Document<DOCDISP> {
| public:
| void drawSummary() { drawFrame( 0, 0, 150, 100, "Summary" ); }
| };

Dans un cas aussi simple, on oublie la factory et on paramètre
directement l'application :
| template <class DOCDISP>
| class Application {
| public:
| void run() {
| Memo<DOCDISP> memo;
| memo.drawSummary();
| }
| };
|
| int main() {
| Application<GraphicDocumentDisplay> app;
| app.run();
| }

Une telle approche est actuellement plutôt prisée par des personnes qui
connaissent bien le langage et est donc globalement plutôt minoritaire.
Parmi les raisons de cette situation je vois :
- la forte présence de langages comme Java ou C# qui ne proposent pas
cette approche (les versions "Generic" restent anecdotiques) et donc le
grand nombre de personnes qui font du C++ comme ils font du Java
- le faible support des templates par certains compilateurs jusqu'à une
période récente (cf les interrogations récurrentes relatives au support
des templates dans VC6)
- un support méthodologique peu adapté (UML se prête beaucoup plus à
décrire des héritages que de paramétrages)
- une complexité de mise au point d'une approche à base de templates
(typage structurel, définitions statiques, ...)

Sur ce, je découvre les "concepts" (dont je ne pense pas avoir saisi le
dixième des utilisations et implications) qui me laissent supposer que,
dans un avenir plus ou moins proche, on pourrait écrire les choses de
manière plus explicites.

Les policy pourraient être nommées et contrôlées avant usage. Si j'ai
bien compris les notions et syntaxes proposées dans l'article, cela
donnerait quelque chose comme :
| template <DOCDISP>
| concept DisplaysDocuments {
| void DOCDISP::drawText( int x, int y, std::string const &text );
| void DOCDISP::drawLine( int x1, int y1, int x2, int y2 );
| };
|
| class GraphicDocumentDisplay {
| public:
| void drawText( int x, int y, std::string const &text );
| void drawLine( int x1, int y1, int x2, int y2 );
| };
|
| model DisplaysDocuments<GraphicDocumentDisplay>;

| template <class DOCDISP>
| class Application where { DisplaysDocuments<DOCDISP> } {
| public:
| void run() {
| Memo<DOCDISP> memo;
| memo.drawSummary();
| }
| };

Et j'ai même l'impression que des implémentations par défaut définies au
niveau des concepts pourraient rendre obsolète une grand pan de
l'utilisation de l'héritage.

En écrivant par exemple ce qui suit, j'ai l'impression d'avoir
entièrement réécrit l'exemple vu précédemment sans utiliser aucun
héritage C++ mais avec l'impression d'avoir quand même fait de l'"objet"
(s'il est encore possible de définir ce terme...) mais "autrement".
| template <DOC>
| concept IsDocument {
| typename doc_display;
| require DisplaysDocuments<doc_display>;
|
| doc_display &DOC::display();
|
| void DOC::drawFrame( int x, int y, int w, int h, std::string const
&title ) {
| display().drawLine( x, y, x+w, y );
| display().drawLine( x, y+h, x+w, y+h );
| display().drawText( x, y, title );
| }
| };
|
| template <class DOCDISP>
| class Memo {
| public:
| typedef DOCDISP doc_display;
| doc_display &display() { return display_; }
|
| void drawSummary() { drawFrame( 0, 0, 150, 100, "Summary" ); }
| private:
| DOCDISP display_;
| };
|
| template <class DOCDISP>
| model IsDocument< Memo<DOCDISP> >;

Pour ceux qui auront eu le courage de lire jusqu'ici, j'aimerais savoir
s'ils pensent :
- que je n'ai rien compris aux "concepts" ?
- que ces notions vont avoir un impact technique majeur sur l'écriture
de code en C++ ?
- que ces notions vont avoir un impact sociologique majeur sur le
développement en C++ ?

Je suis plus particulièrement intéressé par l'aspect sociologique des
choses.
J'ai l'impression d'être face à une évolution du même ordre de grandeur
que le passage du C au C++.
Pour tout dire, j'ai même l'impression que le terme C++ n'est conservé
que pour des raisons marketing (la "marque" est déja connue, appréciée,
possède une base de consommateurs, ...)

Il est toujours possible d'écrire du C avec un compilateur C++ mais, sur
une période d'environ 10 ans (en gros les années 90) on est passé d'une
approche majoritaire en termes de structures/procédures a une approche
majoritaire classes/héritages/associations.
Cela a impliqué un changement de principes de modélisation, un
changement de techniques d'écriture de code mais surtout un changement
de mentalité.
Et quand je regarde les efforts qu'il a fallu déployer pour que
l'ensemble des intervenants en arrive à penser les développements plus
ou moins de la même manière, j'ai un peu l'impression, en voyant ces
nouvelles notions qui se profilent à l'horizon, que nous ne sommes pas
au bout de nos peines...

10 réponses

Avatar
Gabriel Dos Reis
Olivier Azeau writes:

[...]

| J'ai croisé la route d'un certain nombre d'applis avec du C++ dedans
| qui, certes, ne sont probablement pas représentatives de quoi que ce
| soit et je n'ai jamais vu un tel coût rédhibitoire.

Mais, cela peut être un frein à la compréhension des propos des
autres. Cela n'est pas parce que tu n'en en as pas vus que cela
n'existe pas.

| Ceci étant dit, personne ne fait du tout-dynamique pour le plaisir
| d'en faire : il arrive parfois à quelqu'un qui n'utilise jamais de
| templates de mettre autre chose que des pointeurs comme membres de ses
| classes.

une question intéressante cependant est de savoir ce que ce quelqu'un
mettrait d'autre et pourquoi.

[...]

| En fait, la remarque de James ne me surprend pas car j'ai souvent vu
| de près des parties de systèmes qui ne faisaient "rien", en tout cas

souvent ne veut pas dire la majorité des cas et il semble que toi et
James dites « souvent » et refusez de faire de la place à la partie
complémentaire.

[...]

| Tout ça pour dire que je pense continuer mes essais pour mieux
| comprendre les templates et les notions encore plus avancées qui s'y
| rapportent mais sans grand dessein quant à leur utilisation en tant
| que vulgus pecum du développement C++ (du moins pas avant une décade)

ah mais je ne suis pas sur que tu as besoin de ce longueur de thread
pour ça :-/

-- Gaby
Avatar
Ivan Vecerina
"Alain Naigeon" wrote in message
news:4204038c$0$602$
"Ivan Vecerina" a écrit dans le
message news: cu0s5d$jn2$

On ne perd certainement pas en puissance et en flexibilité
en faisant du tout-object et tout-dynamique. Cependant, même
dans des applications banales, ceci a un coût souvent
rédhibitoire.


C'est marrant, quand il s'est agi de passer de C à C++,
on affirmait le contraire à ceux qui émettaient des doutes
(ou qui ne voyaient pas ce qu'on gagnait en temps de
mise au point et en sécurité)


L'orienté-objet introduit par le C++ n'a rien à voir avec
le dynamisme quasi-total offert par un language comme SmallTalk.
Pour info, voir par exemple: http://www.objs.com/x3h7/smalltalk.htm
L' Objective-C, sur lequel NeXT fut basé, avait intégré ce dynamisme
au C: métaclasses, possibilité de filtrer ou déléguer les messages
reçus par un objet, ou de modifier et d'étendre dynamiquement
les méthodes d'une classe.

Le C++ a intégré la programmation objet au C, mais sous une
forme "light" et peu couteuse en performance. Fonctions virtuelles
pour le polymorphisme, et un rudiment d'embryon d'introspection
avec typeinfo -- pas comparable à l'OO dynamique pur du SmallTalk.

Aujourd'hui encore, Java, CLR/.NET, etc, sont loin d'aller aussi
loin dans le dynamisme et l'orienté objet.


Salutations,
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form


Avatar
Ivan Vecerina
"Olivier Azeau" wrote in
message news:ITTMd.20578$
Ivan Vecerina wrote:
| wrote in message
|news:
|Quel rapport ? Quand les templates conviennent, on utilise les
|templates. Quand l'héritage convient, on utilise l'héritage. Les
|deux sont là pour une raison, et c'est même plutôt rare que
|leurs champs d'applications se récouvrent.

On ne perd certainement pas en puissance et en flexibilité
en faisant du tout-object et tout-dynamique. Cependant, même
dans des applications banales, ceci a un coût souvent
rédhibitoire.


Qu'est-ce qui définit "souvent" ? (qui finalement n'est qu'un synonyme de
"la plupart")


Souvent ici est un très doux euphémisme.
Voir ma réponse à Alain Naigeon pour voir ce que signifie
le "tout-objet et tout-dynamique" dans un language comme SmallTalk.
Peux-tu me citer quelques applications commerciales écrites en SmallTalk?
Il y en a par contre beaucoup d'écrites en Objective-C, language
hybride qui permet à certains niveaux de tirer profit d'un dynamisme
accru. Hybride étant le mot clef.

J'ai croisé la route d'un certain nombre d'applis avec du C++ dedans qui,
certes, ne sont probablement pas représentatives de quoi que ce soit et je
n'ai jamais vu un tel coût rédhibitoire.
Je me demande alors pourquoi on utilise encore le type de base 'char',

alors qu'une classe avec des fonctions virtuelles serait certainement
plus flexible.

C'est pour pouvoir manipuler des données (relativement) brutes
et pas tout-à-fait encapsulée derrière des objets et des messages
que l'on doit se résoudre à avoir recours à d'autres formes
de dispatching et de réutilisation de code.


C'est quoi ces données brutes ?
Des données qui ne sont pas pleinement encapsulées, car accessibles

autrement que par l'envoi de messages interprétés dynamiquement
par une classe.

Le résultat, en C++, est effectivement que l'on a des champs
d'application relativement distincts pour les templates et
les fonctions virtuelles/héritages.


En l'état actuel, je vois surtout des champs sociologiques distincts : des
connaisseurs++ qui font des templates et les autres.
Qu'est-ce qui distinque ces deux classes (sociales) ?

Je ne vois pas ici une dychotomie claire mais un continuum.


|Si tu régardes autour de toi, tu verras que la plupart des
|programmes font bien peu de choses, en somme.

Qu'est-ce qui définit "la plupart" ?
La même chose que ce qui définit "souvent".



Peut-on comparer "la plupart des programmes font bien peu de choses"
à "le coût du tout-objet tout-dynamique est (souvent) redhibitoire" ?


En fait, la remarque de James ne me surprend pas car j'ai souvent vu de
près des parties de systèmes qui ne faisaient "rien", en tout cas rien de
bien compliqué au niveau technique : pas de calcul, pas d'algorithme
complexe, pas de gros jeux de données, pas trop de classement de données,
de l'affichage (mais avec des composant tiers qui prennent en charge le
gros du boulot), du stockage de données (mais sans toucher au disque car
le SGBD est là pour ça), du réseau (au pire avec des sockets)
Somme toute, tout programme se compose de séquences de code qui reçoivent

quelques entrées, en génèrent quelques unes, et font appel à d'autre
composants pour faire le gros du boulot. On est d'accord :)

Et des applis qui ne font pas tout ça, il y en a des tas parce qu'un des
gros besoin (sinon le plus gros) c'est de (bien) relayer l'information
entre les quelques morceaux qui eux font vraiment quelque chose.

Dans tout ce code qui ne fait rien, généralement là pour répondre aux
besoins (changeants) des utilisateurs, on se soucie des performances mais
sans jamais, pour ainsi dire, remettre en cause le typage dynamique.
Ce dont ce code a surtout besoin c'est d'être lisible par le plus grand
nombre (genre Paris-Match ou Télé 7 jours) et d'être écrit le plus
rapidement possible (mêmes exemples). Donc écrire une classe template =
OVNI sauf pour certains cas maîtrisés (des traits par exemple)


Nous sommes également d'accord sur le fait que, avec la syntaxe offerte
actuellement par les templates, l'usages de certains outils génériques
est rendue difficile. J'ai déjà exprimé ce point de vue, et dit que ce
pouvait être là un intérêt possible des "concept"s.

Un meilleur exemple serait les lambdas, dont l'objectif est similaire.
Car il est bien plus aisé (les lecteurs de Paris-Match qui programment
en Python pourront te le dire), d'écrire quelque chose du genre:
for_each( myList.begin, myList.end, item = item+1 );
que d'écrire une boucle 'for' à la C qui se prête bien mieux à des bugs.

Les raisons techniques qui font que ce code est écrit en C++ se résument
souvent à un langage compilé (le C) et facile à lire (le ++)
Drôle de définition très personelle du C++ ;)


Les autres raisons sont souvent plus sociologiques (terrain connu,
ressources humaines, réputation, ...)

Tout ça pour dire que je pense continuer mes essais pour mieux comprendre
les templates et les notions encore plus avancées qui s'y rapportent mais
sans grand dessein quant à leur utilisation en tant que vulgus pecum du
développement C++ (du moins pas avant une décade)


....
Je suis certain qu'il n'y avait aucun jugement personnel dans la remarque
mais il faut quand même avouer que les besoins en connaisseurs de C++ de
haut niveau (j'entends par là le besoin d'une connaissance qui va au delà
d'une programmation à la Java) ne courent pas les rues (ou alors c'est que
ceux qui en ont besoin l'ignorent)
Il se pourrait bien que ce dernier point soit correct.

Pour le reste, je prendrais presque ton commentaire pour un compliment,
si j'osais. Mon domaine, c'est plutôt la conception d'applications
médicales, incluant souvent imagerie, simulations, et/ou robotique.

Voilà qui me coupe l'envie de poursuivre.


Il est fort probable par ailleurs que ce thread ait assez duré...


Disons qu'il a été fortement 'bruité'.
Sur le fond, il n'est pas tout mauvais.


Salutations,
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form


Avatar
Olivier Azeau
Gabriel Dos Reis wrote:
Olivier Azeau writes:
| J'ai croisé la route d'un certain nombre d'applis avec du C++ dedans
| qui, certes, ne sont probablement pas représentatives de quoi que ce
| soit et je n'ai jamais vu un tel coût rédhibitoire.

Mais, cela peut être un frein à la compréhension des propos des
autres. Cela n'est pas parce que tu n'en en as pas vus que cela
n'existe pas.


Certes, je précise d'ailleurs la non-représentativité.

Tu as coupé les propos d'Ivan "Cependant, même dans des applications
banales, ceci a un coût souvent rédhibitoire." auxquels je répondais :
le "souvent" n'a aucune justification ici.

| Ceci étant dit, personne ne fait du tout-dynamique pour le plaisir
| d'en faire : il arrive parfois à quelqu'un qui n'utilise jamais de
| templates de mettre autre chose que des pointeurs comme membres de ses
| classes.

une question intéressante cependant est de savoir ce que ce quelqu'un
mettrait d'autre et pourquoi.


Oui... Beaucoup de questions, peu de réponses en fin de compte.

| En fait, la remarque de James ne me surprend pas car j'ai souvent vu
| de près des parties de systèmes qui ne faisaient "rien", en tout cas

souvent ne veut pas dire la majorité des cas et il semble que toi et
James dites « souvent » et refusez de faire de la place à la partie
complémentaire.


Peut-être, mais, dans le message originel, je mets en avant certains
aspects qui n'ont finalement que peu de rapport avec la technique "pure"
du C++ (contexte multi-langages des développeurs, mentalités et
méthodologies dominantes, ...) et la majorité de la discussion porte sur
les mérites techniques comparés des diverses approches qui n'ont, de mon
point de vue, que peu de rapport avec l'interrogation initiale.

Je ne doute pas que nombre de personnes, bien représentées ici
semble-t-il, maîtrisent plutôt bien les templates, les utilisent
couramment dans leurs applications (pour des raisons de performance, de
sécurité, etc...) et voient dans les évolutions du C++ un moyen encore
plus efficace de poursuivre dans cette voie.

Ce qui est beaucoup plus flou en revanche c'est l'impact sur une
*majorité* de développeurs, qui font du C++ (mais aussi du java, du
javascript, du VB, ...), qui n'ont jamais écrit de classe template mais
qui dans un tel cas le feraient surement et qui n'ont de toutes façons
qu'une vision très lointaine du pourquoi de ces évolutions.

J'ai l'impression que ce genre d'impact ne concerne pas (ou très peu) la
"partie complémentaire", d'ou probablement certaines incompréhensions.

Avatar
Richard Delorme
"Alain Naigeon" writes:

| "Ivan Vecerina" a �crit dans le
| message news: cu0s5d$jn2$
| >
| > On ne perd certainement pas en puissance et en flexibilit�
| > en faisant du tout-object et tout-dynamique. Cependant, m�me
| > dans des applications banales, ceci a un co�t souvent
| > r�dhibitoire.
|
| C'est marrant, quand il s'est agi de passer de C � C++,
| on affirmait le contraire � ceux qui �mettaient des doutes
| (ou qui ne voyaient pas ce qu'on gagnait en temps de
| mise au point et en s�curit�)

Je ne comprends pas ce que tu veux dire. Il est possible d'écrire des
programmes inefficaces dans n'importe quel langage.
Cependant, la possibilité d'exprimer certaines choses directement en
C++ peut amener en fait à gagner en efficacité.

http://www.research.att.com/~bs/new_learning.pdf


Le point central de cet article consiste à calculer la médiane d'une
série de double, en utilisant qsort en C, et sort en C++. Le programme
en C++ est à la fois plus élégant, plus sûr, plus court et, surtout,
plus rapide que la version C. Cela met en évidence la supériorité
indéniable de la bibliothèque standard C++ sur la bibliothèque C standard.
Le problème qui m'interpelle, c'est qu'il existe un l'algorithme pour
calculer la médiane plus efficace que celui là, en utilisant un
quicksort partiel et non total. Si quelqu'un souhaite calculer la
médiane de manière efficace, il va bien sûr ouvrir un livre sur les
algorithmes numériques et coder ex-nihilo l'algorithme, qui sera a peu
près identique en C et en C++, ou, s'il est chanceux, utiliser une
bibliothèque tierce toute prête.
Dans ma pratique quotidienne, j'utilise principalement des algorithmes
inexistants dans les bibliothèques standards, et je dirais que 90 à 95%
de mon code consiste en ces algorithmes, et seulement 5 à 10% dans
l'utilisation des bibliothèques standards. Je ne suis donc pas convaincu
de l'importance de l'avantage de la bibliothèque srandard C++ sur celle
du C.

--
Richard

Avatar
Loïc Joly
Richard Delorme wrote:

Le point central de cet article consiste à calculer la médiane d'une
série de double, en utilisant qsort en C, et sort en C++. Le programme
en C++ est à la fois plus élégant, plus sûr, plus court et, surtout,
plus rapide que la version C. Cela met en évidence la supériorité
indéniable de la bibliothèque standard C++ sur la bibliothèque C standard.
[...]

Dans ma pratique quotidienne, j'utilise principalement des algorithmes
inexistants dans les bibliothèques standards, et je dirais que 90 à 95%
de mon code consiste en ces algorithmes, et seulement 5 à 10% dans
l'utilisation des bibliothèques standards. Je ne suis donc pas convaincu
de l'importance de l'avantage de la bibliothèque srandard C++ sur celle
du C.


Je ne pense pas que ce soit la seule conclusion à tirer de l'article. Si
tu écris ton propre algorithme qui ne soit utilisable qu'à un seul
endroit, effectivement, il n'y a pas d'avantage du C++ par rapport au C.
Par contre, si ton algorithme est destiné à enrichire une boîte à outil
que tu te fais, tu peux en C++ écrire cet algorithme plus efficacement
qu'en C.

--
Loïc

Avatar
Olivier Azeau
Ivan Vecerina wrote:
"Olivier Azeau" wrote in
message news:ITTMd.20578$
Qu'est-ce qui définit "souvent" ? (qui finalement n'est qu'un synonyme de
"la plupart")


Souvent ici est un très doux euphémisme.
Voir ma réponse à Alain Naigeon pour voir ce que signifie
le "tout-objet et tout-dynamique" dans un language comme SmallTalk.
Peux-tu me citer quelques applications commerciales écrites en SmallTalk?


Je ne connais pas SmallTalk mais je connais un projet "célèbre" qui
l'utilise : http://c2.com/cgi/wiki?ChryslerComprehensiveCompensation

[...]
J'ai croisé la route d'un certain nombre d'applis avec du C++ dedans qui,
certes, ne sont probablement pas représentatives de quoi que ce soit et je
n'ai jamais vu un tel coût rédhibitoire.


Je me demande alors pourquoi on utilise encore le type de base 'char',
alors qu'une classe avec des fonctions virtuelles serait certainement
plus flexible.


Cela fait longtemps que je n'utilise plus char et char* que quand on me
l'impose (appels systèmes par exemple)
Il y a probablement de bonnes raisons d'utiliser char dans certains cas
mais je crains fort que la majorité des utilisations qui garnissent
nombre d'applications ne soient dues à la méconnaissance de std::string
ou a des optimisations prématurées.

Pour la petite histoire, il m'arrive d'utiliser en entretien une classe
ayant un attribut char* et un attribut int. Peu de candidats arrivent à
exprimer que cette classe *modélise* une "string" (alors que le code ne
laisse par ailleurs aucun doute sur l'utilisation de l'int comme
longueur de la chaîne). Pour la plupart, cette classe *contient* une
chaîne de caractères (= l'attribut "char*") et un int.
Sur ce point, le schéma de pensée du C est bel et bien toujours présent,
à tel point que nombre d'entre eux sont visiblement troublés par
l'absence de test sur le caractère nul pour déterminer la fin de la
chaîne dans l'opérateur d'affectation.

[...]
Le résultat, en C++, est effectivement que l'on a des champs
d'application relativement distincts pour les templates et
les fonctions virtuelles/héritages.


En l'état actuel, je vois surtout des champs sociologiques distincts : des
connaisseurs++ qui font des templates et les autres.


Qu'est-ce qui distinque ces deux classes (sociales) ?
Je ne vois pas ici une dychotomie claire mais un continuum.


Oui... jamais tout blanc ou tout noir...
Mais je ne pense pas que l'on puisse nier le petit fossé culturel qui
caractérise ceux qui écrivent des classes templates

[...]
Un meilleur exemple serait les lambdas, dont l'objectif est similaire.
Car il est bien plus aisé (les lecteurs de Paris-Match qui programment
en Python pourront te le dire), d'écrire quelque chose du genre:
for_each( myList.begin, myList.end, item = item+1 );
que d'écrire une boucle 'for' à la C qui se prête bien mieux à des bugs.


Oui, tout ce qui va dans le sens d'un code plus lisible est bon car
utilisable par le plus grand nombre -- tant que le prix de cette
lisibilité ne se paie pas par des comportements inattendus.

Pour ce qui est des lambdas, je reste circonspect
- quant à leur réelle utilité dans des cas simples
- quant à leur lisibilité dans des cas complexes

Les raisons techniques qui font que ce code est écrit en C++ se résument
souvent à un langage compilé (le C) et facile à lire (le ++)


Drôle de définition très personelle du C++ ;)


Plus un constat qu'une définition :-/



Avatar
Alain Naigeon
"Ivan Vecerina" a écrit dans le
message news: cu1rmc$13o$

Le C++ a intégré la programmation objet au C, mais sous une
forme "light" et peu couteuse en performance. Fonctions virtuelles
pour le polymorphisme, et un rudiment d'embryon d'introspection
avec typeinfo -- pas comparable à l'OO dynamique pur du SmallTalk.


Ok, et merci pour les précisions. Ceci dit, le typeinfo est venu pas mal
de temps après les débuts. Et je me souviens de certains arguments :
pourquoi voulez-vous connaître le type d'un objet à l'exécution,
puique justement les fonctions virtuelles vous permettent de ne pas vous
en soucier...

--

Français *==> "Musique renaissance" <==* English
midi - facsimiles - ligatures - mensuration
http://anaigeon.free.fr | http://www.medieval.org/emfaq/anaigeon/
Alain Naigeon - - Strasbourg, France

Avatar
Gabriel Dos Reis
"Alain Naigeon" writes:

| "Ivan Vecerina" a écrit dans le
| message news: cu1rmc$13o$
|
| > Le C++ a intégré la programmation objet au C, mais sous une
| > forme "light" et peu couteuse en performance. Fonctions virtuelles
| > pour le polymorphisme, et un rudiment d'embryon d'introspection
| > avec typeinfo -- pas comparable à l'OO dynamique pur du SmallTalk.
|
| Ok, et merci pour les précisions. Ceci dit, le typeinfo est venu pas mal
| de temps après les débuts. Et je me souviens de certains arguments :
| pourquoi voulez-vous connaître le type d'un objet à l'exécution,
| puique justement les fonctions virtuelles vous permettent de ne pas vous
| en soucier...

J'ai entendu d'autres arguments : une volonté délibérée de ne pas
rendre la RTTI aussi « attrayant » que les fonctionnalités b asées sur
le typage statique. Le but à demi-avoué est d'encourager le
programmeur à écrire son code de sorte que la structure statique ne
soit pas trop éliogné de la structure dynamique. Pour plus de d étails,
voir D&E.

Cela n'a jamais été un argument contre la RTTI.

-- Gaby
Avatar
Ivan Vecerina
"Richard Delorme" wrote in message
news:4204a71c$0$26213$
Je ne comprends pas ce que tu veux dire. Il est possible d'écrire des
programmes inefficaces dans n'importe quel langage.
Cependant, la possibilité d'exprimer certaines choses directement en
C++ peut amener en fait à gagner en efficacité.
http://www.research.att.com/~bs/new_learning.pdf


Le point central de cet article consiste à calculer la médiane d'une série
de double, en utilisant qsort en C, et sort en C++. Le programme en C++
est à la fois plus élégant, plus sûr, plus court et, surtout, plus rapide
que la version C. Cela met en évidence la supériorité indéniable de la
bibliothèque standard C++ sur la bibliothèque C standard.
Le problème qui m'interpelle, c'est qu'il existe un l'algorithme pour
calculer la médiane plus efficace que celui là, en utilisant un quicksort
partiel et non total.


Il existe effectivement un algo plus efficace pour trouver la médiane
(ou des percentiles/quartiles). Celui-ci est disponible dans la
librairie standard C++ sous le nom de std::nth_element.
Cependant cet algo n'a pas d'équivalent dans la librairie C. Je pense
donc que c'est pour ne pas handicaper le C que Bjarne s'en est tenu
à l'approche 'idiomatique', comme décrit dans l'article, du tri total.

Si quelqu'un souhaite calculer la médiane de manière efficace, il va bien
sûr ouvrir un livre sur les algorithmes numériques et coder ex-nihilo
l'algorithme, qui sera a peu près identique en C et en C++, ou, s'il est
chanceux, utiliser une bibliothèque tierce toute prête.

Dans ma pratique quotidienne, j'utilise principalement des algorithmes
inexistants dans les bibliothèques standards, et je dirais que 90 à 95% de
mon code consiste en ces algorithmes, et seulement 5 à 10% dans
l'utilisation des bibliothèques standards. Je ne suis donc pas convaincu
de l'importance de l'avantage de la bibliothèque srandard C++ sur celle du
C.


Avant tout, il nous faut parler uniquement des algorithmes s'appliquant
à des collections d'éléments -- car c'est là le point focal des STL.

La STL n'a pas la prétention d'être complète, mais elle offre un modèle
qui peut facilement être étendu, et des noyeaux d'algorithmes pouvant
être utilisés au sein d'opérations plus complexes.
Il m'arrive souvent p.ex. de faire un peu de traitement d'image, et il
est évident que la STL n'a rien pour (données pas linéaires mais
en matrice 2D ou 3D). Cependant, il existe nombre d'opérations dont
l'implémentation peut être facilitée par l'emploi de la STL, pour des
sous-parties d'algos.


Salutations
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form