L'avantage du C++ c'est avant tout le RAII.
Pouvoir redéfinir les sémantiques de copie, d'affection, de construction et de destruction de nouveaux types qu'on définit permet de ne pas avoir à faire de gestion manuelle des ressources (comme la mémoire) en garantissant que tout est libéré même face à des erreurs qui surviennent durant l'exécution (exceptions).
À lui seul, cet idiome empêche 90% des défauts de C d'apparaître (gestion de mémoire manuelle, fuites mémoires, dangling pointers...).
Le deuxième avantage, c'est la programmation générique. On peut programmer des composants réutilisables sans avoir à utiliser du typage ou du dispatch dynamique.
Les langages de la famille ML se vantent de leur polymorphisme paramétrique et de leurs modules, mais les fonctionnalités pour la programmation générique de C++ (les templates) permettent bien plus de choses, et sont plus faciles à comprendre pour un programmeur proche du système (mais peut-être pas pour un fan de lambda-calcul).
Celle-ci peut toutefois parfois être compliquée si on veut réaliser certaines choses car nécessitant d'exploiter un peu de méta-programmation pour vérifier certaines propriétés sur les types. De bons outils, comme ceux de boost, peuvent toutefois fortement aider.
La programmation générique sera grandement simplifiée par l'introduction en C++0x des concepts. Ceux-ci permettent de vérifier simplement certaines propriétés sur des types, d'une façon similaire à l'héritage, mais de manière non-intrusive (sans que le type soit explicitement défini comme sous-typant un certain autre type -- le sous-typage est implicite).
Certains aspects de la programmation générique resteront toujours complexes et pour les gurus, comme la réalisation d'un DSEL, même si boost.proto aide beaucoup.
L'héritage permet d'avoir du polymorphisme dynamique à la Java, ce qui est souvent synonyme de programmer plus ou moins à la Java, avec des pointeurs dans tous les sens, de la sémantique d'entité et de la gestion de mémoire "globale" (refcounting ou GC).
Bien évidemment, programmer avec l'héritage, une sémantique de valeur et une gestion de mémoire "non globale" peut se faire, mais en pratique ce n'est pas fait.
Les gens adeptes de cette approche, quand ils codent proprement, utilisent alors plutôt shared_ptr.
La mode actuelle vers laquelle se dirige le C++ moderne est cependant de ne pas utiliser l'héritage, mais de préférer le sous-typage implicite non-intrusif, comme les concepts donc, et avec des objets valeurs (qui restent implémentés par des fonctions virtuelles et des templates sous le capôt) .
Un exemple populaire étant function<R (T1... TN)>, qui permet de contenir un objet de n'importe quel type à partir du moment où on peut l'appeler avec la signature choisie. D'autres exemples plus génériques sont boost.any et choses similaires.
Le futur étant quelque chose dans le genre de adobe::poly -- qui a eu quelques publications scientifiques ces derniers temps [1] --, qui permet vraiment d'avoir de la programmation générique comme avec les templates avec du polymorphisme dynamique au lieu du polymorphisme statique qui les caractérise.
L'héritage multiple etc. est vraiment très peu utilisé. Principalement par la programmation par contrats ou par les frameworks fortement orientés objet (comme le sont bien souvent les GUI toolkits).
Donc réellement, les aspects intéressants du C++ sont le RAII et les templates.
Dire que ce sont des fonctionnalités complexes uniquement pour utilisateurs avancés me semble donc une aberration.
Si ces aspects ne sont pas bien connus par la personne, ou pas utilisés, je pense donc que celle-ci passe vraiment à côté de ce qu'est C++.
[^] # C++ : RAII et programmation générique
Posté par loufoque . En réponse à la dépêche Sortie de GCC 4.3. Évalué à 8.
Pouvoir redéfinir les sémantiques de copie, d'affection, de construction et de destruction de nouveaux types qu'on définit permet de ne pas avoir à faire de gestion manuelle des ressources (comme la mémoire) en garantissant que tout est libéré même face à des erreurs qui surviennent durant l'exécution (exceptions).
À lui seul, cet idiome empêche 90% des défauts de C d'apparaître (gestion de mémoire manuelle, fuites mémoires, dangling pointers...).
Le deuxième avantage, c'est la programmation générique. On peut programmer des composants réutilisables sans avoir à utiliser du typage ou du dispatch dynamique.
Les langages de la famille ML se vantent de leur polymorphisme paramétrique et de leurs modules, mais les fonctionnalités pour la programmation générique de C++ (les templates) permettent bien plus de choses, et sont plus faciles à comprendre pour un programmeur proche du système (mais peut-être pas pour un fan de lambda-calcul).
Celle-ci peut toutefois parfois être compliquée si on veut réaliser certaines choses car nécessitant d'exploiter un peu de méta-programmation pour vérifier certaines propriétés sur les types. De bons outils, comme ceux de boost, peuvent toutefois fortement aider.
La programmation générique sera grandement simplifiée par l'introduction en C++0x des concepts. Ceux-ci permettent de vérifier simplement certaines propriétés sur des types, d'une façon similaire à l'héritage, mais de manière non-intrusive (sans que le type soit explicitement défini comme sous-typant un certain autre type -- le sous-typage est implicite).
Certains aspects de la programmation générique resteront toujours complexes et pour les gurus, comme la réalisation d'un DSEL, même si boost.proto aide beaucoup.
L'héritage permet d'avoir du polymorphisme dynamique à la Java, ce qui est souvent synonyme de programmer plus ou moins à la Java, avec des pointeurs dans tous les sens, de la sémantique d'entité et de la gestion de mémoire "globale" (refcounting ou GC).
Bien évidemment, programmer avec l'héritage, une sémantique de valeur et une gestion de mémoire "non globale" peut se faire, mais en pratique ce n'est pas fait.
Les gens adeptes de cette approche, quand ils codent proprement, utilisent alors plutôt shared_ptr.
La mode actuelle vers laquelle se dirige le C++ moderne est cependant de ne pas utiliser l'héritage, mais de préférer le sous-typage implicite non-intrusif, comme les concepts donc, et avec des objets valeurs (qui restent implémentés par des fonctions virtuelles et des templates sous le capôt) .
Un exemple populaire étant function<R (T1... TN)>, qui permet de contenir un objet de n'importe quel type à partir du moment où on peut l'appeler avec la signature choisie. D'autres exemples plus génériques sont boost.any et choses similaires.
Le futur étant quelque chose dans le genre de adobe::poly -- qui a eu quelques publications scientifiques ces derniers temps [1] --, qui permet vraiment d'avoir de la programmation générique comme avec les templates avec du polymorphisme dynamique au lieu du polymorphisme statique qui les caractérise.
L'héritage multiple etc. est vraiment très peu utilisé. Principalement par la programmation par contrats ou par les frameworks fortement orientés objet (comme le sont bien souvent les GUI toolkits).
Donc réellement, les aspects intéressants du C++ sont le RAII et les templates.
Dire que ce sont des fonctionnalités complexes uniquement pour utilisateurs avancés me semble donc une aberration.
Si ces aspects ne sont pas bien connus par la personne, ou pas utilisés, je pense donc que celle-ci passe vraiment à côté de ce qu'est C++.
[1] http://www.emarcus.org/papers/MPOOL2007-marcus.pdf
http://www.emarcus.org/papers/MPOOL2007-slides-marcus.pdf (même chose sous forme de slides)