Accéder à la programmation du langage C++ avec la POO, au langage de script JAVASCRIPT et à la structuration Cascading Style Sheets grâce à mes travaux
Version imprimable
Accéder à la programmation du langage C++ avec la POO, au langage de script JAVASCRIPT et à la structuration Cascading Style Sheets grâce à mes travaux
Salut,
Quelques réactions "à chaud" lors d'une première lecture :D
En fait, en C++ on appelle "fonction membre" les fonctions qui font partie d'une classe...Citation:
à savoir une association des données et des procédures (qu’on appelle alors méthodes)
Le terme méthode est réservé (d'après strutroup du moins) pour définir une fonction membre virtuelle (n'oublies pas que toute fonction membre n'est pas forcément virtuelle, contrairement au java ;))
Hummm...Citation:
L’encapsulation des données présente un intérêt manifeste en matière de qualité de logiciel. Elle facilite considérablement la maintenance : une modification éventuelle de la structure des données d’un objet n’a d’incidence que sur l’objet lui-même ; les utilisateurs de l’objet ne seront pas concernés par la teneur de cette modification (ce qui n’était bien sûr pas le cas avec la programmation structurée).
A vrai dire, l'encapsulation est régulièrement utilisée en C ;)
Penses, par exemple, au pointeur sur FILE, dont on n'a strictement aucun besoin (ni moyen) de savoir de quoi il est composé !
Par contre, nous pourrions dire que la POO "généralise" ou plutot "systématise" le recours à l'encapsulation ;)
Le chapitre sur l'héritage est vraiment "léger léger" :aie: Un petit mot sur LSP et ce qu'il implique serait sympa ;)
Après tout, l'héritage et le polymorphisme sont les deux ingrédients qui permettent de mettre en place la substituabilité, et il est réellement dangereux d'y recourir pour autre chose (par exemple, pour récupérer du code ) ;)
En fait, je ferais plutôt le contraire:Citation:
Cependant, l’utilisation des symboles déclarés dans ce fichier iostream fait appel à la notion d’espace de noms, introduite elle-aussi par la norme. Cette notion sera présentée ultérieurement. Pour l’instant, sachez qu’elle oblige à introduire dans votre programme une instruction de déclaration using, dont la portée se définit comme celle de toute déclaration, et qui se présente ainsi :(et les exemples de codes qui précèdent ;))
introduire la notion d'espace de noms et préciser que tout ce qui vient du standard se trouve dans l'espace std
indiquer que l'espace de noms intervient dans la reconnaissance des symboles et qu'il doit donc être utilisé de manière systématique lorsque l'on souhaite accéder à un symbole qui en fait partie
expliquer que la directive using permet d'éviter d'avoir à préciser l'espace de noms à chaque fois mais
insister sur le fait qu'elle ne doit pas être utilisée n'importe où et qu'il est préférable d'y recourir quand on a vraiment affaire à des espaces de noms en cascade ( ex : truc::machin::brol::bidule ;) )
Le code qui suit cette phrase :
Personnellement, j'ai horreur d'avoir plusieurs déclarations de variables sur une même ligne, surtout si ce sont des variables de types différents : il est tellement facile de "passer à coté" d'une déclaration en faisant cela :aie:
Au fait, le prototype de la fonction main, c'est int main() ou int main( int argc, char * argv[]), faudrait l'indiquer correctement (et ne pas oublier le retour en fin de fonction ;) )
Pour autant que je sache (mais bon, je suis un peu rouillé en C :aie:) on en peut pas déclarer une fonction au sein d'une fonction en C (et on ne peut d'ailleurs pas non plus le faire en C++ :P ) ;)
Concernant new et delete : attention : new attend un delete et new[] attend un delete[] ;)
concernant les fonction inline préciser que l'on demande au compilateur d'agir de la sorte, mais qu'il reste le dernier à décider de le faire ou non (en fonction du nombre d'instructions à inliner, principalement ;))
Concernant la structure point : introduit peut etre la notion de constructeur, pour virer cette horrible fonction "initialise" :D , cela donnera tout de suite "les bonnes habitudes" ;) (n'oublies pas qu'en C++, struct et class sont identique à la visibilité par défaut des membres près ;))
Ouh lala... mon dieu!!! non!!!Citation:
On notera que, si un destructeur est privé, il ne pourra plus être appelé directement, ce qui n’est généralement pas grave, dans la mesure où cela est rarement utile.
Le destructeur est tout aussi indispensable que le constructeur, autrement, il est impossible d'invoquer delete (ou pire, n'importe quelle instance de la classe créée sur la pile ne sera correctement détruite) ;)
Le destructeur fait partie des "big four" de la forme canonique de coplien, ce n'est pas un hasard ;)
De plus, constructeur et destructeur privés ne seront envisageables que si l'on dispose de fonctions membres statiques ou d'amitiés déclarées qui y feront appel, autrement, il sera impossible de créer ou de détruire l'objet, et la classe devient donc inutilisable ;)
concernant system("PAUSE"): donnes peut etre directement les bonnes habitudes en te basant sur la FAQ pour créer une pause de manière standard ;) (linux, pour ne citer que lui, ne dispose pas de l'instruction système "pause" :D )
je lirai la suite plus tard ;)
suffit de commencer par la fin
La recherche de 'Delannoy' sur ce forum montrera la limite de cette référence ... (par expl, ici ou ici ou ici).Citation:
CONCLUSION :
Toutefois, pour plus de détails, nous vous renvoyons à l’ouvrage de Claude Delannoy « C++ pour les programmeurs C »
Pour apprendre le dév, Programmation - Principes et pratique avec C++, de Bjarne Stroustrup
Pour sa défense, il est autorisé d'omettre le retour à la fin du main ; et alors un return 0; est ajouté implicitement. ;)Citation:
Envoyé par koala01
salut tout le monde,
merci pour vos contributions, j'ai vraiment approuvé et ça me permets de mieux me parfaire.
Par ailleurs pour le :
- retour en fin de ligne, je programme avec DEVCPP, et je pense que c'est gérer automatiquement mais par contre sous turbo cpp, le retour est gérer par le programmeur lui même.
- Merci 3Darchi pour le tuyau
- Vrai que toutes fonction membre n'est pas forcément virtuel sinon ça serait caduque, mais j'ai voulu mettre l'accent que dans une classe on a les membres données et les fonctions membres ou méthodes car dans la plupart des ouvrages c'est cette appellation que je rencontre.
En parlant de programmation structurée c'est plutôt le C standard ou le pascal que je faisais allusion mais merci quand même.
- Pour initialise(), j'essayais d'introduire petit à petit les notions de fonctions membres et même dans la suite je l'ai remplacé par un constructeur. Merci pour la précision avec new et delete
- Pour les constructeurs et destructeurs je comprend pas très bien ce que vous avez voulu dire mais j'ai précisé qu'ils étaient indispensable pour bien encapsuler les données et qu'il serait préférable de les rendre public pour ne pas avoir a les appeler par d'autres méthodes
- Merci pour l'astuce avec system("pause"), j'ai l'habitude de programmer sous window avec DEVCPP
Au prix minimum d'un avertissement, voir d'une erreur de compilation si tu compile avec l'option ad-hoc ;)
DevCpp n'est plus maintenu depuis des années, et ce n'est vraiment pas une bonne idée de continuer à l'utiliser (et encore moins d'inciter des débutants à l'utiliser)...
Tournes toi peut etre vers Code::blocks :D
Quant à TurboCpp, c'est un EDI qui date, ou peu s'en faut, d'avant la normalisation du langage, et c'est donc encore pire que d'utiliser DevCpp ;)
- Merci 3Darchi pour le tuyau
Note que c'est ce que certains langages (que je ne citerai pas :D) ont pris comme principe ;)Citation:
- Vrai que toutes fonction membre n'est pas forcément virtuel sinon ça serait caduque,
Cela dépend vraiment des ouvrages, et de l'approche du lecteur ;)Citation:
mais j'ai voulu mettre l'accent que dans une classe on a les membres données et les fonctions membres ou méthodes car dans la plupart des ouvrages c'est cette appellation que je rencontre.
Personnellement, je trouve sympa le fait de faire une différence entre une fonction membre (non virtuelle) et une méthode (fonction membre virtuelle), et j'ai l'impression que de plus en plus de gens sont du même avis... Autant en promouvoir l'usage :D
C'est, justement, en pensant au C que j'ai fait la remarque (tu n'as aucun besoin de connaitre le contenu de la structure FILE pour l'utiliser... c'est grâce à l'encapsulation :D )Citation:
En parlant de programmation structurée c'est plutôt le C standard ou le pascal que je faisais allusion mais merci quand même.
Le fait est que cela fait penser au "C with classes", et que c'est une approche contre laquelle on se bat depuis des années ;)Citation:
- Pour initialise(), j'essayais d'introduire petit à petit les notions de fonctions membres et même dans la suite je l'ai remplacé par un constructeur.
mais de rien ;)Citation:
Merci pour la précision avec new et delete
Quelques petits rappels pour te faire comprendre :Citation:
- Pour les constructeurs et destructeurs je comprend pas très bien ce que vous avez voulu dire mais j'ai précisé qu'ils étaient indispensable pour bien encapsuler les données et qu'il serait préférable de les rendre public pour ne pas avoir a les appeler par d'autres méthodes
- Même lorsque l'on n'a pas recours à l'allocation dynamique de la mémoire, le constructeur est automatiquement appelé lorsque l'on déclare une variable du type de la classe, et le destructeur est automatiquement appelé lorsque l'on quitte la portée dans laquelle la variable en question a été déclarée
- Tout ce qui se trouve dans l'accessibilité private d'une classe (ou d'une structure, vu que c'est kif kif en C++ ;)) n'est accessible que par les fonctions membres de la classe en question, et par les fonctions statiques de la classes en question.
S'il n'y a pas une fonction statique qui fait appel explicitement au constructeur (ou au destructur) et que celui-ci est privé, il devient impossible de construire (ou de détruire) une instance de la classe visée...
La classe devient donc totalement inutile ;)
Mais autant donner tout de suite de bonnes habitudes, y compris celle d'utiliser une méthode permettant d'assurer la portabilité du programme, chaque fois que possible ;)Citation:
- Merci pour l'astuce avec system("pause"), j'ai l'habitude de programmer sous window avec DEVCPP
Au passage, le fait d'utiliser l'instruction "system" fait d'office appel à un appel au niveau du système d'exploitation, ce qui, pour certaines instructions, risque de plomber littéralement les perfs ;)
Tu me diras sans doute qu'appeler system("PAUSE") à la fin d'un programme ne nuira pas aux perfs, mais, si cela implique l'habitude de le faire chaque fois qu'une pause est nécessaire, voir d'invoquer l'instruction system pour d'autres choses... :aie:
@koala01: Tu as un warning quand tu mets pas de return à la fin d'un main ? Tu as testé avec quoi ? J'ai rien en WAll sous VC++ 2010 et en WAll + WExtra sous gcc (mingw) 4.6.2. C'es completement standard de ne rien mettre à la fin d'un main.
En effet, au temps pour moi...
Je n'avais pas vérifié avant de poster, mais, en effet, main est une fonction qui peut ne pas avoir de return :aie:
C'est, finalement, assez étrange quand on sait que, pour tout autre fonction n'ayant pas void comme type de retour, tu auras un avertissement si tu n'a pas le "return" (Gcc 4.7 -wreturn-type ) ;)
Oui ca m'avait un peu choqué quand j'ai vu ca, mais bon, ca fait partie des petites choses qui font que main est une fonction spéciale ^^.
(très bonne initiative de venir se soumettre à la critique chez les pinailleurs perfectionnistes que nous sommes :))
a- "Comme on peut s’en douter, l’héritage facilite largement la réutilisation de 0produits existants"
Arg.
Toujours ce même mensonge des années 80. Tu es une victime de vieux arguments commerciaux qui sont malheureusement à côté de la plaque.
Nous savons réutiliser depuis les routines (gosub, fonctions, & cie).
La force et l’intérêt premier de l'héritage réside dans la substituabilité. C'est une nécessité en vue de supporter le polymorphisme d'inclusion.
b- "surdéfinition"
Elevé au Delannoy ?
La traduction répandue de "overloading" est "surcharge". Et "redéfinition" (bien que "supplantation" soit plus juste) pour "overriding" -- note qu'en anglais, c'est "over" qui revient et pas la partie de droite ...
c- Euh dans les nouveaux trucs par rapport au C, il y a le RAII, les exceptions, et les templates (dans les trucs les plus visibles qui font toute la différence)
Accessoirement, tu as deux entrées "spécificités"
d- "initialise()"
graaaa. Pourquoi parler de comment il ne faut pas faire? (c'est années 90 cette approche, pour ceux qui découvraient la POO après 15 ans de C ou de Pascal)
Pars directement sur la bonne fonction -> le constructeur
(tiens j'avais manqué des messages => +1 pour dégager initialise)
e- des char* avant std::string
ça sent l'approche historique tout ça...
Modernise ton cours.
Sincèrement. Cela fait partie des autres trucs contre lesquels on se bat => avoir un C++ maintenable et robuste même et surtout chez les débutants
f- Décidément, je reconnais que trop bien le support sur lequel tu t'appuie.
Je t'invite à consulter un ouvrage moderne d'apprentissage du C++
-> Accelerated C++ de Koenig et Moo chez Addisson-Wesley (non traduit)
-> Je me Lance (plus édité) de Francis Glassborrow
-> Pratiques et Principes de Programmation en C++ de Stroustrup
g- Le destructeur de vect appelle le mauvais delete.
C'est une remarque générale, car je note l'erreur plus d'une fois.
h- On a deux sémantiques typiques en C++
- entité (où l'on interdit la copie et l'affectation, typique des classes où il y a un héritage public)
- valeur (où l'on supporte copie, affectation, et comparaison)
Quand on traite de la sémantique de valeur, et que l'on doive spécifier la copie, il faut alors toujours spécifier également l'affectation.
Cf FAQ pour des bonnes façons.
=> Tout ça pour dire que j'en suis aujourd'hui arrivé à la conclusion de deux chapitres un pour les valeurs, un pour les entités, et de montrer les bonnes façons de procéder et accessoirement d'utiliser des exemples typiques de chaque sémantique.
i- 'int pleine()' C'est du C ça.
En C++ -> "bool est_pleine() const"
La const-correction a été passée sous silence bien trop longtemps.
Et je vois bien d'autres endroits où tu n'utilises pas le type booléen.
j- p63: "delete ( tab + nelet-1);"
quoi ?
Cela n'a pas le moindre sens.
k- exit()
Ne leur montre pas exit(). C'est une fonction fortement déconseillée en C++ car elle ne provoque pas la destruction des variables locales. Elle va du coup à l'encontre du RAII. Si le programme doit absolument nettoyer un truc en se terminant, il ne pourra plus forcément le faire.
l- je t'invite à lire l'entrée de la FAQ (c++lite ?) au sujet de l'amitié.
Tel que tu formules, on pourrait croire qu'il s'agit d'une rupture d'encapsulation alors que c'est tout le contraire.
D'ailleurs quand tu écris: "une telle déclaration d'amitié les autorise alors à accéder aux données privées, au même titre que n'importe quelle fonction membre", oui c'est exactement pour ça qu'il ne s'agit pas d'une rupture d'encasulation.
BTW, pour matrice * vecteur, il est naturel d'exposer les éléments, cela fait parti de leur interface.
Plus loin, enseigne leur de suite le passage par référence constante et non le passage par copie. Je suis sûr que tu ne veux pas que tes élèves soient pris de haut par qu'ils plombent les perfs sur des trucs aussi idiots.
m- de nouveau, tu me sembles avoir un nombre d'heures limitées -- vu que je n'ai pas vu une seule trace des exceptions&RAII, de la const-correction, etc. Ne le gaspille pas en montrant ce qu'ils ne doivent pas faire. Montre-leur au contraire la façon définitive de procéder -> opérateurs mathématiques surchargés et pas mult/add/prod etc.
n- à ce sujet ->lien externe<- vers une écriture (interface) type des opérations mathématiques.
o- mauvais choix de classe pour illustrer l'héritage.
Il y a de beaux mélanges (insolubles! si, si!) entre valeurs et entités (induite par l'héritage) entre des points et des pointcol
De nouveau une fonction initialisesec ... c'est le mal!
p- initialise() n'est pas une redéfinition, c'est une surcharge masquante!
redéfinition rime avec virtual.
q- je vois un tableau de dérivation (public, etc)
Je crois que je m'étais fait avoir aussi dans le passé.
Ce n'est pas ça l'important. Là, on parle de syntaxe et pas d'intention.
D'intentions, on n'en a que deux
- importer du code et rien d'autre
- être substituable (avec éventuellement import de code)
cas1 -> héritage privé
cas 2 -> héritage public
Le pourquoi ? Eventuellement, tu peux montrer le tableau ... en annexe. Mais ce n'est pas ça l'important.
r- "point (point & p)"
Pas const-correct
Et tu vas dans le mur à vouloir donner une sémantique de copie (/valeur) à des trucs tirés d'une hiérarchie. Le slicing va te rattraper.
Solution ? Prendre un exemple où il est indubitable que les objets manipulés sont bien des entités et qu'il n'y a aucun sens à les copier.
s- <<que la classe A est "virtuelle">>
Une classe virtuelle ne veut rien dire. -> http://www.developpez.net/forums/d11...e/#post6304603 (4 dernières lignes)
Attention, tu pars sur un terrain glissant à montrer l'héritage multiple sans avoir parler préalablement du LSP.
t- Remonte d'un cran ton chapitre sur les fonctions virtuelles, il est 100 fois plus important que celui sur l'héritage multiple.
De plus il n'y a pas de redéfinition sur des fonctions non virtuelles.
C'est la définition.
u- Très bien, il fait parler des std::string
Mais tu le fais beaucoup trop tard.
v- dans la famille la bonne pratique d'abord, fais dériver tes exceptions de std::exception
Ou plus simplement commencer par montrer comment utiliser les exceptions standard, puis éventuellement comment on écrit une classe d'exception.
Et surtout, initie-les au RAII.
w- s/exit/return/
exit, c'est aussi le mal
x- Ah! j'avais reconnu la patte de l'ouvrage qui a inspiré ton cours.
Ne prends donc pas personnellement toutes les critiques que l'on peut faire. Elle ne viennent pas de toi. Juste d'un support qui appartient à une famille de supports que nous combattons.
Résultat d'un échantillonnage.
- main sans type de retour? Si je ne me trompe pas, c'est interdit même en C de nos jours.
- change les feuilles de style décrivant le code. Il y a trop d'espace vertical. (Les autres feuilles de styles sont a revoir aussi par quelqu'un ayant des notions de typographie; du gras italique souligné, ça fait mal aux yeux)
- indentation aléatoire
- on n'utilise float que quand il faut stocker beaucoup de données, et on fait quand même les calculs (et tous les résultats intermédiaires autant que possible) en double (sauf cas particuliers qui sont hors sujet vu le reste du cours)
- "La version 3 de C++ a intégré", c'est très 1991 (date de la sortie de la version 3, de nos jours a ce niveau la, on se fout de tout ce qui précède la norme, 1998).
- new de tableau -> a remplacer par des vector, pour moi technique avancée hors sujet
- new nothrow -> trop avance a mon avis vu le reste du cours
- pas de mention de la découpe en hpp/cpp? C'est pourtant difficile de faire quoi que ce soit sans la mettre en pratique. (A mentionner au minimum: gardes d'inclusion, pas de using dans les hpp, utilisation des declarations plutot que des definitions; a rementionner quand on traite des templates car la découpe naturelle n'est pas possible)
Merci à vous tous,
Je constate que j'ai encort des pas à faire dans le C++, en faites j'apprends la programmation tout seul car mon domaine c est l electronique et la télécommunication et je compte sur vous tous pour les eventuelles contributions.