Et puis pour revenir au C++, les on-dits et ce genre de dépêche ont un effet assez dissuasifs sur moi. Je suis plutôt à l'aise en C
Je vais en profiter pour parler de ce que j'apprécie dans le C++, ça changera du thread ou les défauts sont listés :)
Pour moi, les principaux avantages du C++ sur le C (qui à été mon 1er «vrai» langage), c'est qu'il permets d'automatiser plus le code source, sans forcément avoir recours à des trucs capilo-tractés. Certes, on peut faire des trucs complexes, mais tout ne l'est pas.
Typiquement, les 3 (5 en fait, si on compte le const_cast et le cast old school qui est toujours valide) casts de C++ ont un gros avantage sur celui du C, ils permettent d'éviter pas mal de bugs.
J'ajouterais en 2ème position les template.
Pas la STL (la STL, c'est un concentré de C++: classes, templates, exceptions), juste les templates (la SL possède de beaux exemples comme std::sort déjà mentionné) qui permettent de quasi-supprimer les macros, tout en permettant un code plus lisible et plus sûr (les types sont vérifiés à la compilation). Malheureusement, je ne crois pas (mais je n'ai pas vérifié) qu'il soit aussi simple de manipuler des chaînes de caractères de la même manière en template qu'en macros, donc ces derniers ont toujours leur utilité ( ## et #, même si c'est illisible, m'on déjà été utiles ).
Par exemple, j'ai un template qui permets de caster d'un type vers un autre, et si il y a dépassement (enfin, j'ai pas fait une couverture de test à 100% et j'ai testé que sur des pointeurs et des entiers), ça fait assert ratée. En release, ça ne fait que dalle. Accessoirement, il est plus court à taper que static_cast ;)
J'aurai sûrement pu coder ça à coup de macros, mais je pense que j'aurai dépassé la 60aine de lignes (et j'aime bien aérer en hauteur).
En 3ème position, les fonctions à l'intérieur des structures, plus clairement: les constructeurs et destructeurs: fini de devoir se rappeler d'appeler SDL_FreeFooBar(ptr);.
Contrairement à l'idée reçue, pas besoin d'exceptions ni d'héritage pour en tirer bon profit. Dans le cas de l'héritage, je dirais même que c'est de toute façon un truc que j'évite, comme probablement pas mal de monde et ce, dans tous les langages.
En standard, on a std::unique_ptr, mais, ça ne gère que les pointeurs (et ce n'est pas le seul reproche que j'ai envers unique_ptr, mais comme je l'ai dis, je ne considère pas la STL comme le principal point fort de C++, au risque de me faire descendre :)): pas les resources indexées (handles de fichier, de ressources OpenGL, whatever). Du coup, j'ai une classe qui gère l'unicité des ressources, et qui sait que -1, c'est l'équivalent de nullptr. Enfin, en réalité, elle ne le sait pas: je lui ai collé un paramètre template pour indiquer quelle valeur est équivalent d'une ressource vide.
4ème: la SL. C'est à dire la bibliothèque standard sans les conteneurs. Je ne dis pas qu'ils sont inutiles, mais ils ont les «inconvénients»:
de lancers des exceptions (et on peut pas faire autrement) dans différents cas.
de ne pas permettre de contrôler facilement l'usage mémoire (sauf std::array et, dans une moindre mesure, std::vector. std::map/set et leurs versions multi sont souvent implémentées en RBtree, pas sûr pour les unordered, et de toute façon le standard n'impose rien me semble).
En revanche, la SL, c'est des algo plus ou moins classiques et complexes à faire qu'on peut utiliser d'une ligne. Enfin, surtout depuis c++11, parce qu'avant les lambda et std::begin()/std::end() c'était un peu pénible :)
Le reste, pour moi, ce sont des plus, mais pas les killer features du C++ (surtout du point de vue d'un dev C, j'imagine):
Quand t'as la flemme de faire tes propres conteneurs, tu peux utiliser la STL.
Et si t'as envie de faire tes conteneurs (genre un ring buffer ou un dictionnaire dont on peut connaître l'usage mémoire), mais que tu ne veux pas réécrire les algorithmes standards, tu as juste à implémenter un itérateur: tu bénéficies toujours des algo de la SL.
Bien sûr, le récent fait de pouvoir utiliser les algo sur des tableaux C-style est bien pratique, ainsi que le range for (peut-être qu'il existe aussi en C11? Je ne sais pas du tout ce qu'ils ont ajouté.).
Et pour finir, les exceptions et les flux: beaucoup les aimes, d'autres non, mais dans certains tout ça est bien utile.
En conclusion: tu devrais essayer. Juste, dans un premier temps, remplacer gcc par g++ (ou clang par clang++ ou... bref) et les casts. C'est plus verbeux c'est vrai, mais ça réduit les problèmes.
Puis avec les templates et la RAII, tu te retrouves déjà avec des codes bien plus réduits que leurs versions C, sans être obligé de libérer explicitement les instances de BDD (chose qu'il faut faire manuellement tant en C qu'en Java si on se méfie du côté aléatoire du GC) et sans forcément avoir un code plus dur à lire, même s'il est vrai que plus on combine de techniques, plus le code deviens délicat à manipuler. D'où l'intérêt d'intégrer les avantages au fur et à mesure (et avec le temps de considérer certains morceaux comme peu utiles en regard des services rendus).
[^] # Re: Jai: Language for game programmming
Posté par freem . En réponse à la dépêche C++17, Genèse d’une version mineure. Évalué à 7.
Je vais en profiter pour parler de ce que j'apprécie dans le C++, ça changera du thread ou les défauts sont listés :)
Pour moi, les principaux avantages du C++ sur le C (qui à été mon 1er «vrai» langage), c'est qu'il permets d'automatiser plus le code source, sans forcément avoir recours à des trucs capilo-tractés. Certes, on peut faire des trucs complexes, mais tout ne l'est pas.
Typiquement, les 3 (5 en fait, si on compte le const_cast et le cast old school qui est toujours valide) casts de C++ ont un gros avantage sur celui du C, ils permettent d'éviter pas mal de bugs.
J'ajouterais en 2ème position les template.
Pas la STL (la STL, c'est un concentré de C++: classes, templates, exceptions), juste les templates (la SL possède de beaux exemples comme std::sort déjà mentionné) qui permettent de quasi-supprimer les macros, tout en permettant un code plus lisible et plus sûr (les types sont vérifiés à la compilation). Malheureusement, je ne crois pas (mais je n'ai pas vérifié) qu'il soit aussi simple de manipuler des chaînes de caractères de la même manière en template qu'en macros, donc ces derniers ont toujours leur utilité ( ## et #, même si c'est illisible, m'on déjà été utiles ).
Par exemple, j'ai un template qui permets de caster d'un type vers un autre, et si il y a dépassement (enfin, j'ai pas fait une couverture de test à 100% et j'ai testé que sur des pointeurs et des entiers), ça fait assert ratée. En release, ça ne fait que dalle. Accessoirement, il est plus court à taper que
static_cast;)J'aurai sûrement pu coder ça à coup de macros, mais je pense que j'aurai dépassé la 60aine de lignes (et j'aime bien aérer en hauteur).
En 3ème position, les fonctions à l'intérieur des structures, plus clairement: les constructeurs et destructeurs: fini de devoir se rappeler d'appeler
SDL_FreeFooBar(ptr);.Contrairement à l'idée reçue, pas besoin d'exceptions ni d'héritage pour en tirer bon profit. Dans le cas de l'héritage, je dirais même que c'est de toute façon un truc que j'évite, comme probablement pas mal de monde et ce, dans tous les langages.
En standard, on a std::unique_ptr, mais, ça ne gère que les pointeurs (et ce n'est pas le seul reproche que j'ai envers unique_ptr, mais comme je l'ai dis, je ne considère pas la STL comme le principal point fort de C++, au risque de me faire descendre :)): pas les resources indexées (handles de fichier, de ressources OpenGL, whatever). Du coup, j'ai une classe qui gère l'unicité des ressources, et qui sait que -1, c'est l'équivalent de nullptr. Enfin, en réalité, elle ne le sait pas: je lui ai collé un paramètre template pour indiquer quelle valeur est équivalent d'une ressource vide.
4ème: la SL. C'est à dire la bibliothèque standard sans les conteneurs. Je ne dis pas qu'ils sont inutiles, mais ils ont les «inconvénients»:
En revanche, la SL, c'est des algo plus ou moins classiques et complexes à faire qu'on peut utiliser d'une ligne. Enfin, surtout depuis c++11, parce qu'avant les lambda et std::begin()/std::end() c'était un peu pénible :)
Le reste, pour moi, ce sont des plus, mais pas les killer features du C++ (surtout du point de vue d'un dev C, j'imagine):
Quand t'as la flemme de faire tes propres conteneurs, tu peux utiliser la STL.
Et si t'as envie de faire tes conteneurs (genre un ring buffer ou un dictionnaire dont on peut connaître l'usage mémoire), mais que tu ne veux pas réécrire les algorithmes standards, tu as juste à implémenter un itérateur: tu bénéficies toujours des algo de la SL.
Bien sûr, le récent fait de pouvoir utiliser les algo sur des tableaux C-style est bien pratique, ainsi que le range for (peut-être qu'il existe aussi en C11? Je ne sais pas du tout ce qu'ils ont ajouté.).
Et pour finir, les exceptions et les flux: beaucoup les aimes, d'autres non, mais dans certains tout ça est bien utile.
En conclusion: tu devrais essayer. Juste, dans un premier temps, remplacer gcc par g++ (ou clang par clang++ ou... bref) et les casts. C'est plus verbeux c'est vrai, mais ça réduit les problèmes.
Puis avec les templates et la RAII, tu te retrouves déjà avec des codes bien plus réduits que leurs versions C, sans être obligé de libérer explicitement les instances de BDD (chose qu'il faut faire manuellement tant en C qu'en Java si on se méfie du côté aléatoire du GC) et sans forcément avoir un code plus dur à lire, même s'il est vrai que plus on combine de techniques, plus le code deviens délicat à manipuler. D'où l'intérêt d'intégrer les avantages au fur et à mesure (et avec le temps de considérer certains morceaux comme peu utiles en regard des services rendus).