OVH Cloud OVH Cloud

Trois strates dans C++ ?

76 réponses
Avatar
Marc Boyer
Bonjour à tous,

risquant d'avoir à faire un cours de C++, je réflechissais
un peu à la présentation générale, à la hiérarchisation des
connaissances en C++.

Je vois actuellement 3 strates dans C++:

I. "C++ as a better C"

C++ comme un langage impératif procédural, sans objet
utilisateur (ie presque que des POD), une sorte de C
augmenté par les E/S iostream, iofstream, les conteneurs
STL (vector, list..), string, les itérateurs et les algos
(find, remove...)
Et puis surtout les références et const.
Eventuellement la surcharge des opérateurs.

II. C++ comme un Java-like

Introduction des objets, methodes, encapsulation
(public/private).
Vie de l'objet: constructeur/destructeur, opérateur
de copie, constructeur de copie, tous public.

Héritage public / polymorphisme dynamique: virtual...

III. C++ comme support à la conception

Tout ce qui permet à C++ de gérer des patterns
particuliers: les opérateurs de vie de l'objet privé,
l'héritage privé.

Et puis il y a aussi l'écriture de ses propres classes
templates, qui me semble possible sérieusement qu'après
avoir intégré le II, que je mets donc là même si c'est
peut-être orthogonal.


Cette réflexion me semble importante car C++ est
souvent rejetté de par sa complexité. Et c'est vrai
qu'il me semble que beaucoup de l'agitation autour de
C++ se fait dans le III, que c'est peut-être la partie
intellectuellement la plus exitante, mais qu'elle ne
peut qu'effrayer la majorité des débutants.

Voilà, dans mon cours, je viserais plutôt I et II.

Marc Boyer
--
Entre le fort et le faible, c'est la liberte qui opprime et le droit
qui libere. Henri Lacordaire, Dominicain

10 réponses

1 2 3 4 5
Avatar
kanze
Fabien LE LEZ wrote:
On Wed, 22 Feb 2006 14:18:13 +0100, Laurent Deniau
:

Non, dans basics je n'aborderais rien qui soit lie a la STL
basic porterait plutot sur [char,int,unsigned,double],


Se passer totalement de tableaux et de chaînes pendant
plusieurs chapitres, ça risque d'être dur à gérer, non ?
Après tout, ce sont des types presque aussi fréquents que
"int", et (au moins dans mon code) très largement plus
fréquents que "double".


Est-ce que ça ne dépend pas du domaine d'application ? D'après
son adresse email, Laurent travaille au CERN, un centre de
récherche scientifique où, j'imagine, les double servent
énormement. Tandis que les chaînes de caractères, c'est surtout
les étiquettes d'affichage, donc, des chaînes littérales. Si tes
applications gèrent du texte, les rapports risquent d'être bien
différents.

Ceci dit, je ne vois pas trop de problème dans l'introduction du
type std::string (sinon qu'il faut parler de std:: -- mais dans
un premier temps, c'est juste une convention de nommage un peu
particulière, qui touche string et cout).

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
kanze
Laurent Deniau wrote:
Fabien LE LEZ wrote:
On Wed, 22 Feb 2006 15:36:46 +0100, Laurent Deniau
:

Si tu veux tout de meme utiliser string ou vector, tu peux
preparer un include fait-mains dans lequel tu mets des
typedefs ou des macros pour que les eleves ne voit pas
l'aspect template


Pourquoi ?


Parce qu'un simple typedef vector<int> int_vec + une
utilisation de [] sans explication est tres proche de int v[].


Jusqu'au moment que tu le passes comme paramètre, ou que tu veux
l'utiliser comme résultat d'une fonction.

L'intérêt principal de se servir de std::vector ici, c'est qu'il
est un type entier, sans règles spéciales, conversion implicite
en pointeur, etc.

Un autre intérêt, c'est que je ne vois pas trop l'intérêt à
introduire un type, seulement pour dire plus tard qu'il ne faut
jamais s'en servir -- et puis pour en revenir dans le cour
expert pour expliquer qu'il y a des fois particulières où son
utilisation se justifier, pour des raisons de l'ordre de
construction, par exemple.

Le seul point eventuellement positif d'utiliser tout de suite
vector, c'est la verification de l'index, mais lorsque
l'exception apparaitra, il te faudra au moins 15min
d'explication du pourquoi du comment de ce que voit l'etudiant
a ce stade du cours.


Les implémentations g++ et (je crois) VC++ ont des versions
debug de la bibliothèque, ce qui fait qu'une erreur d'indice
donne un core dump. Or, les core dumps, les élèves vont en voir,
et très vite, que tu le veuilles ou non. Ce n'est donc pas ça
qui va leur introduire quelque chose de nouveau.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34



Avatar
kanze
Loïc Joly wrote:
On Wed, 22 Feb 2006 17:19:13 +0100, Laurent Deniau
:

Parce qu'un simple typedef vector<int> int_vec + une
utilisation de [] sans explication est tres proche de int
v[].


Tu peux rajouter push_back assez vite.


Et size


Surtout size(), je crois -- bien vu.

En fait, je crois qu'on pourrait arriver assez vite au point où
un des devoirs serait de calculer le moyen des valeurs dans un
tableau. Alors, du coup : avec double[], il faut expliquer la
conversion implicite en pointeur, l'arithmétique des pointeurs,
etc., et il faut passer la taille explicitement comme paramètre,
ce qui suppose qu'on la gère manuellement. Alors qu'avec
std::vector< double >, c'est un type comme un autre, qui obéit
aux même règles (passage par valeur, sauf si on se sert d'une
référence, etc.), et qui gère sa taille internalement.

Il me semble clair lequel des deux est la plus facile à
présenter.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34



Avatar
Laurent Deniau
kanze wrote:
Laurent Deniau wrote:

Fabien LE LEZ wrote:

On Wed, 22 Feb 2006 12:15:03 +0100, Laurent Deniau
:




basics (type, var, func, loop, TU)
overloading I (func)
template I (func)
overloading II (op)





STL-use I (vector, iostream, iterator, algoI)
[...]
STL-use II (string, map, iostream, algoII)





J'imagine que par "vector", "iostream" et "string", tu
entends "étude des détails de ces machins", car tu as abordé
les bases de l'utilisation de ces trois-là dans "basics" ?




Non, dans basics je n'aborderais rien qui soit lie a la STL



Seulement que ça ne marche pas. Les élèves vont vouloir afficher
des résultats -- ils sont donc obligés à se servir au moins de
std::cout. Et je vois les tableaux aussi comme quelque chose
d'assez fondamental. Donc, std::vector.


Quels resultats? On parle d'un cours ou d'un TP? Ce n'est pas du tout la
meme chose. Marc parlait d'un cours. S'il faut faire un TP en plus, je
ne le commencerais pas avant d'avoir vu scope & namespace & lifetime au
minimum.

Le plan que j'ai propose fait expres de taiter les concepts fondamentaux
incrementalement et par cycle pour que 1) l'etudiant ne sature pas sur
un sujet, 2) lui laisser le temps de comprendre les concepts d'un cycle
a l'autre (voir de faire des TP entres) et 3) permettre un
raffraichissement de ce qui a ete vu sur le concept dans le cycle
precedent pour que ca rentre bien et eventuellement donner l'occasion de
poser des questions sur des points qui ne sont pas apparus pendant le
traitement du sujet.

Pour un TP, je mettrais expres un dephasage de quelques points avec le
cours, ce qui est de toute facon necessaire des le depart (cf ta
remarque) et avec un mixage des notions deja traitees decorrele avec le
plan du cours (ca force a revoir des notions parfois lointaines dans
l'esprit des etudiants). Pour le TP il faut mieux etre oriente
application et resultat, c'est plus motivant pour les eleves et plus
facile a gerer. Et pour ca rien n'empeche de dire aux eleves que chaque
TP utilise tout ce qui a deja ete vu du debut de l'annee jusqu'a l'etape
N du cours.

basic porterait plutot sur [char,int,unsigned,double], un ou
deux POD (sous forme de struct), main, qque var, while (pas de
do-while ni de switch, et for je le garde pour plus tard, par
ex avec les iterateurs), qques fonctions, const mais seulement
vu comme du read-only (a-la-C), la notion d'include et de TU
(avec un peu de pp). Qqchose de tres succint mais essentiel
et indispensable pour commencer. Surtout pas commencer un
cours magistral de C ou de C vu du C++.



OK. C'est même plus basic que je ne l'aurais imaginé.


basics, ca doit rester basique! Le but c'est de se familiarise avec la
syntaxe, le processus de compilation, les mot clefs, etc... Pas de
larguer les etudiants.

J'adapterais eventuellement la pertinence de basics au niveau
des eleves, par exemple s'ils ont deja vu le C ou Java a un
niveau avance.



Il me semble que Marc a dit qu'ils connaissent déjà le C. Ce qui


Oui, il l'a precise apres mon post.

change beaucoup. Par exemple, je suis d'accord avec ta rémarque
de ne pas comparer aux autres langages. Mais s'ils connaissent
le C, on ne pourrait pas empécher qu'ils reconnaissent les
ressemblances, et qu'ils font la comparaison eux-mêmes.


Dans ce cas, j'introduirais dans basics (qui du coup est tres court)
quelques remarques/comparaison d'incompatibilite/portabilite entre C et
C++ pour bien marquer le coup que desormait on parle C++ et plus C.

a+, ld.




Avatar
Laurent Deniau
kanze wrote:
Fabien LE LEZ wrote:

On Wed, 22 Feb 2006 14:18:13 +0100, Laurent Deniau
:



Non, dans basics je n'aborderais rien qui soit lie a la STL
basic porterait plutot sur [char,int,unsigned,double],




Se passer totalement de tableaux et de chaînes pendant
plusieurs chapitres, ça risque d'être dur à gérer, non ?
Après tout, ce sont des types presque aussi fréquents que
"int", et (au moins dans mon code) très largement plus
fréquents que "double".



Est-ce que ça ne dépend pas du domaine d'application ? D'après
son adresse email, Laurent travaille au CERN, un centre de
récherche scientifique où, j'imagine, les double servent
énormement. Tandis que les chaînes de caractères, c'est surtout
les étiquettes d'affichage, donc, des chaînes littérales. Si tes
applications gèrent du texte, les rapports risquent d'être bien
différents.


Les string servent aussi enormement. Le point s'etait que ce que
j'ennoncais par basics etait vraiment basique. Je n'envisageait pas plus
de 30-40 min sur le sujet et si les eleves connaissent le C, ca serait
meme 10-15min.

a+, ld.



Avatar
Laurent Deniau
Marc Boyer wrote:

Marc Boyer wrote:

Bonjour à tous,

risquant d'avoir à faire un cours de C++, je réflechissais
un peu à la présentation générale, à la hiérarchisation des
connaissances en C++.

Je vois actuellement 3 strates dans C++:


D'un point de vue general, je ne parlerais pas des autres langages (C
inclu) parce que ca n'apporte rien et ca ne peux que produire des
confusions, ou des racourcis abusifs dans la tete de certains etudiants.



Je suis d'accord, c'était pour situer le débat ici, en faisant
référence à une culture commune.


Et dans la
meme lignee, je commencerais par 10min sur un exemple poilu de
resolution de probleme en C++ sur un sujet de leur domaine, histoire de
calmer ceux qui connaissent deja (croient connaitre) C++ et d'eveiller
la curiosite des autres en abordant un sujet qui les interesse. Tu
pourras aussi revenir dessus une fois les notions necessaires acquises
ce qui leur montrera leur evolution.



Va falloir que j'apprenne l'électronique. Heuh, dans l'idéal,
se serait bien. Mais je sais pas si je vais avoir le temps.


Tu peux t'inspirer de ce qui existe. Sinon en 93 ou 94 pour des
genie-electrique, j'avais fait un tetris. C'est presque l'ideal, simple,
connu, ludique, OO par nature, et pas plus de 150-300 lignes. Mais a
l'epoque c'etait du turbo C++ 1.0 sous DOS et j'attaquais la memoire
video joyeusement ;-) Aujourd'hui il te faudra passer par ncurse mais
normalement, qques fonctions "opaque" devrait faire l'affaire sans
encombrer l'esprit des etudiants.

Du coup ta structure n'est plus appropriee ;-)

Je crois que je suivrais plutot qqchose du genre (a vue de nez):



Je fais un découpage.


basics (type, var, func, loop, TU)
overloading I (func)
template I (func)
overloading II (op)
STL-use I (vector, iostream, iterator, algoI)


string quand même, non ?


eventuellement, surtout comme le dit James tu veux passer au TP dans la
foulee.

scope & namespace & lifetime



C'est ce que je voyais en 'strate I', ie C++ comme langage
impératif procédural moderne.


Absolument.

class I (0 base, encapI)
ctor, dtor I
inheritance I (single)
class II (1 base, encapII)
exception
template II (class)
traits
meta-programming I (factorielle)
STL-use II (string, map, iostream, algoII)
polymorphism I (virtual)
ctor, dtor II (virtual)
inheritance II (multi, virtual)
polymorphism II (multi, virtual)



C'est globalement le II que j'imaginais (avec les templates
en plus, mais vous avez levé certaines de mes réticences).


J'ai constater que les eleves (voir mes collegues) comprennent plus vite
les templates que le polymorphisme d'heritage, que j'ai mis expres vers
la fin du plan pour attendre au maximum que les autres concepts soient
bien digeres. En fait on pourrait penser le contaire parce que
techinquement les templates sont plus compliques que le polymorphisme
d'heritage, mais ils semblent que les concepts eux-memes soient mieux
digerer dans l'autre sens.

STL-use III (alloc)
polymorphism III (covariance, contravariance, vtable)
overloading III (resolution)
template III (resolution)
meta-programming II (intro)
STL-use IV (valarray)



Il manque un mode d'emplois sur certains mécanismes.
Présenter la différence methode publique/privée, c'est facile.
Dire qu'on peut faire un opérateur de copie privé, c'est
une phrase à dire. Mais quand l'utiliser...


La je me rabattrais sur la litterature et les Design Patterns pour le
pourquoi de l'utilite: heritage d'implementation, singleton, atom,
visitor...

Une chose qui me manque dans les cours de C++ que j'ai vu,
c'est qu'on présente des mécanismes relativement indépendants,
sans dire comment s'en servir.


Parce que c'est ce qu'il y a de plus difficile. On voit souvent du tout
template ou du tout virtual. Mixer les deux demande plus d'experience en
design.

a+, ld.



Avatar
kanze
Laurent Deniau wrote:
Marc Boyer wrote:


[...]
Il manque un mode d'emplois sur certains mécanismes.
Présenter la différence methode publique/privée, c'est facile.
Dire qu'on peut faire un opérateur de copie privé, c'est
une phrase à dire. Mais quand l'utiliser...


La je me rabattrais sur la litterature et les Design Patterns
pour le pourquoi de l'utilite: heritage d'implementation,
singleton, atom, visitor...


Et voilà une idée géniale, je trouve. On n'enseigne pas
l'héritage, etc., pour soi. On enseigne quelque modèles de
conception, et en le faisant, on explique les méchanismes du C++
qui permettent à l'implémenter.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
Marc Boyer
Le 23-02-2006, Laurent Deniau a écrit :
Marc Boyer wrote:
Et dans la
meme lignee, je commencerais par 10min sur un exemple poilu de
resolution de probleme en C++ sur un sujet de leur domaine, histoire de
calmer ceux qui connaissent deja (croient connaitre) C++ et d'eveiller
la curiosite des autres en abordant un sujet qui les interesse. Tu
pourras aussi revenir dessus une fois les notions necessaires acquises
ce qui leur montrera leur evolution.



Va falloir que j'apprenne l'électronique. Heuh, dans l'idéal,
se serait bien. Mais je sais pas si je vais avoir le temps.


Tu peux t'inspirer de ce qui existe.


J'ai de vagues souvenirs de terminale (ou prépa ?). Tout circuit
ayant une capacité et une résistance équivalente... Faut voir.

Sinon en 93 ou 94 pour des
genie-electrique, j'avais fait un tetris. C'est presque l'ideal, simple,
connu, ludique, OO par nature, et pas plus de 150-300 lignes. Mais a
l'epoque c'etait du turbo C++ 1.0 sous DOS et j'attaquais la memoire
video joyeusement ;-) Aujourd'hui il te faudra passer par ncurse mais
normalement, qques fonctions "opaque" devrait faire l'affaire sans
encombrer l'esprit des etudiants.


Oui.

basics (type, var, func, loop, TU)
overloading I (func)
template I (func)
overloading II (op)
STL-use I (vector, iostream, iterator, algoI)


string quand même, non ?


eventuellement, surtout comme le dit James tu veux passer au TP dans la
foulee.

scope & namespace & lifetime



C'est ce que je voyais en 'strate I', ie C++ comme langage
impératif procédural moderne.


Absolument.


Bon, on est d'accord.

class I (0 base, encapI)
ctor, dtor I
inheritance I (single)
class II (1 base, encapII)
exception
template II (class)
traits
meta-programming I (factorielle)
STL-use II (string, map, iostream, algoII)
polymorphism I (virtual)
ctor, dtor II (virtual)
inheritance II (multi, virtual)
polymorphism II (multi, virtual)


C'est globalement le II que j'imaginais (avec les templates
en plus, mais vous avez levé certaines de mes réticences).


J'ai constater que les eleves (voir mes collegues) comprennent plus vite
les templates que le polymorphisme d'heritage, que j'ai mis expres vers
la fin du plan pour attendre au maximum que les autres concepts soient
bien digeres. En fait on pourrait penser le contaire parce que
techinquement les templates sont plus compliques que le polymorphisme
d'heritage, mais ils semblent que les concepts eux-memes soient mieux
digerer dans l'autre sens.


J'ai réalise cette année en effet que dans la POO, on se jettais
souvent directement dans les bras du polymorphisme d'héritage sans
insister sur encapsullation et ctor/dtor.
Vous me convainquez (?) de présenter plus tôt les templates.

STL-use III (alloc)
polymorphism III (covariance, contravariance, vtable)
overloading III (resolution)
template III (resolution)
meta-programming II (intro)
STL-use IV (valarray)


Il manque un mode d'emplois sur certains mécanismes.
Présenter la différence methode publique/privée, c'est facile.
Dire qu'on peut faire un opérateur de copie privé, c'est
une phrase à dire. Mais quand l'utiliser...


La je me rabattrais sur la litterature et les Design Patterns pour le
pourquoi de l'utilite: heritage d'implementation, singleton, atom,
visitor...


Oui, sans exemples, présenter ces mécanismes me semble très vain.

Une chose qui me manque dans les cours de C++ que j'ai vu,
c'est qu'on présente des mécanismes relativement indépendants,
sans dire comment s'en servir.


Parce que c'est ce qu'il y a de plus difficile. On voit souvent du tout
template ou du tout virtual. Mixer les deux demande plus d'experience en
design.


Oui, mais aussi mettre en garde contre les difficultés.

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exiter des sots
IF -- Rudyard Kipling



Avatar
Laurent Deniau
Marc Boyer wrote:

Marc Boyer wrote:

Et dans la
meme lignee, je commencerais par 10min sur un exemple poilu de
resolution de probleme en C++ sur un sujet de leur domaine, histoire de
calmer ceux qui connaissent deja (croient connaitre) C++ et d'eveiller
la curiosite des autres en abordant un sujet qui les interesse. Tu
pourras aussi revenir dessus une fois les notions necessaires acquises
ce qui leur montrera leur evolution.



Va falloir que j'apprenne l'électronique. Heuh, dans l'idéal,
se serait bien. Mais je sais pas si je vais avoir le temps.


Tu peux t'inspirer de ce qui existe.



J'ai de vagues souvenirs de terminale (ou prépa ?). Tout circuit
ayant une capacité et une résistance équivalente... Faut voir.


une simulation de circuit RLC ou d'un amplificateur / integrateur
devrait faire l'affaire. Tu devrais effectivement trouver les equations
dans n'importe quel bouquin de prepas (SI?) ou deug de physique. Le
cas echeant tu demandes un livre, voir un exo, au prof d'electronique
qui se fera un plaisir de te conseiller par rapport a son programme.
L'interet de l'electronique c'est que c'est aussi OO par nature ;-) Si
tu t'oriente vers du numerique, tu auras aussi la joie de te frotter aux
bases de temps et a la propagation des fronts dans les circuits ;-)

Sinon google ;-)

J'ai réalise cette année en effet que dans la POO, on se jettais
souvent directement dans les bras du polymorphisme d'héritage sans
insister sur encapsullation et ctor/dtor.
Vous me convainquez (?) de présenter plus tôt les templates.


Disons que de mon point de vue (qui n'engage que moi), je trouve plus
simple et plus logique une transition overload -> template -> subtyping.

Parce que c'est ce qu'il y a de plus difficile. On voit souvent du tout
template ou du tout virtual. Mixer les deux demande plus d'experience en
design.



Oui, mais aussi mettre en garde contre les difficultés.


Normalement, si les concepts sont bien assimiles, les difficultes se
transforment en contraintes qui a leur tour se transforment en regles ou
en pattern.

Il est sur que si dans un chapitre tu melanges heritage multiple,
heritage virtuel, fonctions membres virtuelles, overload, template,
template specialisation, namespace, Koenig-lookup et meta-programming
(ce qui dans la pratique n'arrive pas si rarement que ca), les etudiants
vont devoir s'accrocher.

a+, ld.




Avatar
Marc Boyer
Le 23-02-2006, Laurent Deniau a écrit :
Marc Boyer wrote:
Parce que c'est ce qu'il y a de plus difficile. On voit souvent du tout
template ou du tout virtual. Mixer les deux demande plus d'experience en
design.


Oui, mais aussi mettre en garde contre les difficultés.


Normalement, si les concepts sont bien assimiles, les difficultes se
transforment en contraintes qui a leur tour se transforment en regles ou
en pattern.


Très franchement pas plus tard que la semaine dernière,
je me suis dit 'tiens, celui là, son opérateur de copie devrait
être privé'.
Bon, je m'en suis mordu les doigts, et il redevenu public.

J'espère que ce n'est pas juste pour me disculper de
mon incompétence, mais je crois qu'il y a pas mal
d'expérience aussi.
Avoir compris ce qu'est un constructeur, un destructeur,
un opérateur de copie, c'est une chose. Anticiper que
celui là, on gagne en sécurité en s'en privant...

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exiter des sots
IF -- Rudyard Kipling



1 2 3 4 5