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

4 5 6 7 8
Avatar
Etienne Rousee
"James Kanze" a écrit t...
Etienne Rousee wrote:
"Fabien LE LEZ" a écrit ...
des notions qui n'existent pas en C (string, vector,
fonctions membres, etc.),


On peut mettre des fonctions dans des struct en C.


Depuis quand ? Ce n'est pas dans C99.


Voici un exemple qui compile en turboc 2.0
(Ça ne nous rajeunit pas)
D'accord, ce n'est pas la même chose qu'en C++,
mais c'est une fonction dans une struct:

#include <stdio.h>
#include <conio.h>

typedef struct Point2D Point2D;

struct Point2D
{
double x,y;
void (*aff)(Point2D *);
};

void affiche(Point2D *pt)
{
printf("x = %5.3lf et y = %5.3lfn",pt->x,pt->y);
}

void initPoint(Point2D *pt)
{
pt->x = 3.14;
pt->y = 2.718;
pt->aff = affiche;
}

int main(void)
{
Point2D p;

initPoint(&p);

p.aff(&p);

getch();

return 0;
}

--

Etienne



Avatar
Gabriel Dos Reis
James Kanze writes:

| Laurent Deniau wrote:
| > Fabien LE LEZ wrote:
| >> On Thu, 23 Feb 2006 17:56:24 +0100, Laurent Deniau
| >> :
|
| >>>>> techinquement les templates sont plus compliques que le
| >>>>> polymorphisme d'heritage
|
| >>>> Tiens ? J'aimerais bien que tu m'expliques ça. J'ai
| >>>> toujours trouvé que c'était le contraire.
|
| >>> D'abord BS dit lui-meme dans le D&E que l'implementation des
| >>> templates [...]
|
| >> Ah, OK, tu parles de l'implémentation. Je m'intéressais quant
| >> à moi à l'accès d'un débutant à une fonctionnalité.
|
| > Dans ce cas tu devrais relire ce que j'ai dit: il vaut mieux
| > (selon mes observations) commencer par les templates plus
| > facilement acceptes conceptuellement par les debutants *puis*
| > passer au polymorphisme d'heritage.
|
| Dans quelle mésure ? Je suis assez d'accord pour les templates
| ancienne modèle, que le néophyte considérait un peu comme un
| espèce de macro. Mais je me vois mal expliquer la récherche de
| nom en deux phases à un débuttant.

Pourquoi penses-tu que tu devrais le faire dès le premier jour ?
Je ne pense pas que le débutant qui apprend à *utiliser* des templates
(container et quelques algorithmes de la STL) doive savoir la
recherche de nom en deux phases au début du cours.

-- Gaby
Avatar
Franck Branjonneau
Marc Boyer écrivait:

Le 23-02-2006, Franck Branjonneau a écrit :
Marc Boyer écrivait:

Le 23-02-2006, Fabien LE LEZ a écrit :
On Thu, 23 Feb 2006 15:56:36 +0000 (UTC), Marc Boyer
:

Bon, après, la gestion des erreurs dans le format d'entrée,
je pense que c'est pénible dans les deux langages.


Pour le coup, j'en viens à me demander si c'est pas pire en C++.


Je me demande. Je suis pas expert.
En C, un coup de fgets + scanf, et scanf disant combien
de conversions il a réussit à faire, je vois à peut prêt
comment faire.
En C++, faut tester l'état du flux à chaque fois, non ?


Autant de fois que tu testes le retour de fgets en C.


Non, je voulais parler "d'erreur dans le /format/
d'entrée" et pas dans le fichier d'entrée.


En C++ on ne distingue pas.
Tu auras, par exemple,

in >> date;

et en cas d'échec in.fail() est true.

--
Franck Branjonneau





Avatar
Franck Branjonneau
"Etienne Rousee" écrivait:

"James Kanze" a écrit t...
Etienne Rousee wrote:

On peut mettre des fonctions dans des struct en C.


Depuis quand ? Ce n'est pas dans C99.


typedef struct Point2D Point2D;

struct Point2D
{
double x,y;
void (*aff)(Point2D *);
};


Où est la fonction ?

--
Franck Branjonneau



Avatar
Fabien LE LEZ
On Sat, 25 Feb 2006 12:59:33 +0100, "Etienne Rousee"
:

des notions qui n'existent pas en C (string, vector,
fonctions membres, etc.),


On peut mettre des fonctions dans des struct en C.


On peut mettre des pointeurs de fonctions dans une structure, mais ça
n'en fait pas des fonctions membres, puisque "this" n'est pas passé en
paramètre invisible.


Avatar
Jean-Marc Bourguet
Franck Branjonneau writes:

Marc Boyer écrivait:

Le 23-02-2006, Franck Branjonneau a écrit :
Marc Boyer écrivait:

Le 23-02-2006, Fabien LE LEZ a écrit :
On Thu, 23 Feb 2006 15:56:36 +0000 (UTC), Marc Boyer
:

Bon, après, la gestion des erreurs dans le format d'entrée,
je pense que c'est pénible dans les deux langages.


Pour le coup, j'en viens à me demander si c'est pas pire en C++.


Je me demande. Je suis pas expert.
En C, un coup de fgets + scanf, et scanf disant combien
de conversions il a réussit à faire, je vois à peut prêt
comment faire.
En C++, faut tester l'état du flux à chaque fois, non ?


Autant de fois que tu testes le retour de fgets en C.


Non, je voulais parler "d'erreur dans le /format/
d'entrée" et pas dans le fichier d'entrée.


En C++ on ne distingue pas.


Si, voir la différence entre fail et bad.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org






Avatar
James Kanze
Jean-Marc Bourguet wrote:
Franck Branjonneau writes:


Marc Boyer écrivait:



Marc Boyer écrivait:





On Thu, 23 Feb 2006 15:56:36 +0000 (UTC), Marc Boyer
:







Bon, après, la gestion des erreurs dans le format d'entrée,
je pense que c'est pénible dans les deux langages.
Pour le coup, j'en viens à me demander si c'est pas pire en C++.

Je me demande. Je suis pas expert.

En C, un coup de fgets + scanf, et scanf disant combien
de conversions il a réussit à faire, je vois à peut prêt
comment faire.
En C++, faut tester l'état du flux à chaque fois, non ?
Autant de fois que tu testes le retour de fgets en C.

Non, je voulais parler "d'erreur dans le /format/

d'entrée" et pas dans le fichier d'entrée.
En C++ on ne distingue pas.




Si, voir la différence entre fail et bad.


Ça, c'est en théorie. En fait, les seules fois que tu trouveras
badbit en entrée, c'est si le streambuf lève une exception.
C-à-d jamais, en pratique. C'est bien beau de définir deux
conditions au niveau des flux, mais tant qu'on n'a pas prévu un
moyen de les rapporter des streambuf, on n'est pas bien avancé.

--
James Kanze
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
Franck Branjonneau
Jean-Marc Bourguet écrivait:

Franck Branjonneau writes:

En C, un coup de fgets + scanf, et scanf disant combien
de conversions il a réussit à faire, je vois à peut prêt
comment faire.
En C++, faut tester l'état du flux à chaque fois, non ?


Autant de fois que tu testes le retour de fgets en C.


Non, je voulais parler "d'erreur dans le /format/
d'entrée" et pas dans le fichier d'entrée.


En C++ on ne distingue pas.


Si, voir la différence entre fail et bad.


Toutes mes sources disent :
-- fail : flux consistant ;
-- bad : flux non consistant, en particulier erreur bas niveau.

--
Franck Branjonneau





Avatar
Jean-Marc Bourguet
James Kanze writes:

Jean-Marc Bourguet wrote:
[...]

Si, voir la différence entre fail et bad.


Ça, c'est en théorie. En fait, les seules fois que tu trouveras
badbit en entrée, c'est si le streambuf lève une exception.
C-à-d jamais, en pratique.


Je m'attends à ce que badbit soit mis dans au moins deux cas
sous unix: si il y a un problème renvoyé par read/write ou
si la conversion échoue. C'est difficile de forcer le
premier (du moins pour moi), mais le deuxième c'est aisé
quand un locale UTF-8 est disponible. Essayons:

[~/src]$ cat testbadbit.cc
#include <fstream>
#include <iostream>
#include <istream>
#include <locale>
#include <ostream>
#include <string>

int main() {
std::wfstream s("data");
s.imbue(std::locale(""));
std::cout << "locale is " << s.getloc().name() << 'n';
std::wstring line;
while (std::getline(s, line)) {
}
if (s.fail()) {
std::cout << "fail()n";
}
if (s.bad()) {
std::cout << "bad()n";
}
if (s.eof()) {
std::cout << "eof()n";
}
}
[~/src]$ g++ -Wall -Wextra -o testbadbit testbadbit.cc
[~/src]$ od -t x1 data
0000000 e9 0a
0000002
[~/src]$ ./testbadbit
locale is fr_FR.UTF-8
fail()
bad()

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org


Avatar
kanze
Jean-Marc Bourguet wrote:
James Kanze writes:

Jean-Marc Bourguet wrote:
[...]

Si, voir la différence entre fail et bad.


Ça, c'est en théorie. En fait, les seules fois que tu trouveras
badbit en entrée, c'est si le streambuf lève une exception. C-à-d
jamais, en pratique.


Je m'attends à ce que badbit soit mis dans au moins deux cas
sous unix: si il y a un problème renvoyé par read/write ou si
la conversion échoue. C'est difficile de forcer le premier (du
moins pour moi), mais le deuxième c'est aisé quand un locale
UTF-8 est disponible. Essayons:

[~/src]$ cat testbadbit.cc
#include <fstream>
#include <iostream>
#include <istream>
#include <locale>
#include <ostream>
#include <string>

int main() {
std::wfstream s("data");
s.imbue(std::locale(""));
std::cout << "locale is " << s.getloc().name() << 'n';
std::wstring line;
while (std::getline(s, line)) {
}
if (s.fail()) {
std::cout << "fail()n";
}
if (s.bad()) {
std::cout << "bad()n";
}
if (s.eof()) {
std::cout << "eof()n";
}
}
[~/src]$ g++ -Wall -Wextra -o testbadbit testbadbit.cc
[~/src]$ od -t x1 data
0000000 e9 0a
0000002
[~/src]$ ./testbadbit
locale is fr_FR.UTF-8
fail()
bad()


Intéressant. Il faudrait que je régarde l'implémentation de la
bibliothèque g++ de plus près. Il faut crois qu'il lève des
exceptions en certains cas d'erreur dans filebuf. Est-ce qu'il
le font quand le Posix read() renvoie -1 aussi ? (Je crois que
oui. Au moins si j'ai bien compris le code dans
basic_filebuf<>::underflow().)

C'est une évolution positive. Mes expériences sont, je l'avoue,
avec des implémentations plus anciennes.

--
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



4 5 6 7 8