Aller au contenu principal
HistoireHistoire de l’informatiqueDébutant

C++ : de C with Classes au C++ moderne

De C with Classes aux standards modernes, découvrez comment C++ a concilié abstraction, généricité, compatibilité et contrôle des performances.

Publié le 10 août 2026Mis à jour le 15 septembre 2026Lecture : 11 minPar Yann Bastien
C++ : de C with Classes au C++ moderne
Afficher le sommaire
  1. De C à l’idée de « C with Classes »
  2. 1983 : le langage devient C++
  3. L’orienté objet, mais pas seulement
  4. L’idée centrale : des abstractions sans surcoût imposé
  5. RAII : faire de la durée de vie un outil
  6. Templates et programmation générique
  7. 1998 : C++ devient un standard ISO
  8. C++11 et la naissance du « C++ moderne »
  9. Un rythme d’évolution plus régulier
  10. Pourquoi C++ reste-t-il complexe ?
  11. C++, Java et les compromis de conception
  12. Où C++ reste essentiel
  13. Ce que l’histoire de C++ révèle
  14. Chronologie
  15. Questions fréquentes
  16. C++ est-il simplement une version orientée objet de C ?
  17. Pourquoi C++ reste-t-il compatible avec C ?
  18. Qu’est-ce que le C++ moderne ?
  19. Pourquoi C++ n’utilise-t-il pas un ramasse-miettes obligatoire ?
  20. C++ est-il encore pertinent face à Rust et aux langages plus récents ?
  21. Pourquoi C++ évolue-t-il sans supprimer davantage d’anciennes fonctionnalités ?

C++ occupe une place singulière dans l’histoire des langages de programmation. Depuis la fin des années 1970, il poursuit une ambition difficile : permettre de construire des abstractions puissantes sans renoncer au contrôle des ressources ni aux performances proches de la machine.

Cette tension entre abstraction et contrôle explique une grande partie de son évolution. C++ a adopté les classes, la programmation générique, une vaste bibliothèque standard, la programmation fonctionnelle et la concurrence, tout en conservant une forte continuité avec C et avec plusieurs décennies de code existant.

Le résultat est un langage très puissant, mais aussi complexe. Comprendre son histoire permet de voir que cette complexité n’est pas seulement une accumulation accidentelle : elle vient souvent de choix de compatibilité, de performance et de généralité assumés au fil du temps.

De C à l’idée de « C with Classes »

Au début des années 1970, C s’impose aux Bell Labs comme un outil particulièrement efficace pour développer Unix. Le langage de Dennis Ritchie combine portabilité relative, accès direct à la mémoire et modèle d’exécution simple. Il devient rapidement une référence de la programmation système.

Mais à mesure que les logiciels grandissent, une question se pose : comment structurer des systèmes complexes sans perdre les qualités qui ont fait le succès de C ? Notre article sur l’histoire du langage C revient sur ce contexte.

À la fin des années 1970, Bjarne Stroustrup travaille à Cambridge avec Simula, un langage pionnier de la programmation orientée objet. Il apprécie ses classes et ses mécanismes d’abstraction, mais juge les performances de son environnement insuffisantes pour certains travaux.

Lorsqu’il rejoint les Bell Labs en 1979, l’idée se précise : conserver l’efficacité et l’écosystème de C tout en y ajoutant des abstractions inspirées notamment de Simula. Le projet prend le nom de C with Classes.

Les premières versions proposent entre autres classes, constructeurs et destructeurs, contrôle d’accès et héritage. Stroustrup développe également Cfront, qui traduit le nouveau langage en C avant de laisser un compilateur C produire le programme final. Cette stratégie facilite l’expérimentation et le déploiement sur des plateformes disposant déjà d’outils C.

1983 : le langage devient C++

En 1983, C with Classes reçoit le nom C++, proposé par Rick Mascitti. L’opérateur ++ de C incrémente une valeur : le nom suggère donc un C « augmenté » plutôt qu’un remplacement complet de C.

Le langage enrichit progressivement son modèle avec les fonctions virtuelles, la surcharge de fonctions et d’opérateurs, les références, les constantes et une vérification des types plus poussée. En 1985, la première édition de The C++ Programming Language accompagne sa diffusion hors du cadre expérimental des Bell Labs.

Cette continuité avec C est stratégique. Les programmeurs peuvent réutiliser une partie de leurs connaissances, bibliothèques et outils. Elle aura toutefois un prix durable : C++ devra longtemps concilier ses propres mécanismes avec un héritage conçu avant lui.

Pour approfondir le rôle de son concepteur, voir également la biographie de Bjarne Stroustrup.

L’orienté objet, mais pas seulement

Dans les années 1980 et 1990, la programmation orientée objet gagne en popularité. C++ contribue fortement à cette diffusion grâce aux classes, à l’encapsulation, à l’héritage et aux fonctions virtuelles permettant le polymorphisme dynamique.

Mais réduire C++ à « C avec des objets » devient rapidement trompeur. Le langage n’impose jamais un modèle unique : il permet de combiner fonctions libres, types valeur, classes, héritage, programmation générique et accès direct aux ressources.

Cette approche multiparadigme le distingue de langages qui organisent presque tout autour d’un modèle objet uniforme. Notre histoire de la programmation orientée objet replace cette évolution entre Simula, Smalltalk et les langages qui suivent.

L’idée centrale : des abstractions sans surcoût imposé

Une formule résume une grande partie de la philosophie de C++ : zero-overhead abstractions.

L’idée comporte deux dimensions. Ce qu’un programme n’utilise pas ne devrait pas lui coûter. Et lorsqu’il utilise une abstraction, son coût ne devrait pas être sensiblement supérieur à celui d’une implémentation manuelle équivalente bien écrite.

Cela ne signifie pas que toute abstraction C++ est gratuite. Cela signifie que le langage cherche à permettre au programmeur et au compilateur d’exprimer des abstractions de haut niveau sans imposer systématiquement une machine virtuelle, un ramasse-miettes ou un modèle d’exécution plus lourd.

Cette ambition explique à la fois l’efficacité de C++ et une partie de sa difficulté : exposer précisément les coûts, les durées de vie et les choix de représentation demande davantage de concepts.

RAII : faire de la durée de vie un outil

Constructeurs et destructeurs conduisent à l’un des idiomes les plus caractéristiques de C++ : RAII, pour Resource Acquisition Is Initialization.

Une ressource est associée à la durée de vie d’un objet. Le constructeur peut l’acquérir et le destructeur la libérer automatiquement lorsque l’objet quitte sa portée. La ressource peut être de la mémoire, mais aussi un fichier, un verrou, une connexion ou un descripteur système.

RAII transforme la destruction déterministe des objets en mécanisme général de gestion des ressources. Il reste au cœur du C++ moderne et explique pourquoi les bonnes pratiques actuelles évitent souvent les appels manuels dispersés à new et delete.

Templates et programmation générique

À la fin des années 1980 et au début des années 1990, les templates donnent au langage une nouvelle dimension. Une fonction ou un type peut être paramétré par d’autres types, ce qui permet d’exprimer un algorithme ou une structure de données de manière générique.

Cette évolution est décisive. C++ ne se contente plus d’ajouter de l’orienté objet à C : il devient aussi l’un des grands terrains de la programmation générique.

Les travaux d’Alexander Stepanov et de ses collaborateurs aboutissent à la Standard Template Library, ou STL. Son idée structurante consiste à découpler les conteneurs des algorithmes grâce à des interfaces génériques, notamment les itérateurs.

Des conteneurs comme vector ou map peuvent ainsi être utilisés avec des algorithmes standard de tri, de recherche ou de transformation sans créer une version spécifique de chaque algorithme pour chaque conteneur.

La STL montre concrètement que généricité, réutilisation et performance peuvent coexister. Elle devient une composante majeure de la bibliothèque standard et transforme la manière d’écrire du C++.

1998 : C++ devient un standard ISO

À mesure que les compilateurs se multiplient, le risque de dialectes incompatibles augmente. Un processus international de normalisation devient indispensable.

En 1998, C++ obtient sa première norme ISO complète. C++98 formalise le langage et intègre notamment la STL à la bibliothèque standard. Une révision corrective suit avec C++03.

La normalisation change la gouvernance du langage. C++ n’est plus seulement l’œuvre de son créateur ou d’un fournisseur : son évolution passe par un comité international, des propositions, des implémentations et des compromis entre de nombreux acteurs.

Cette stabilité facilite l’adoption industrielle, mais les années 2000 renforcent aussi la réputation d’un langage puissant et difficile. Gestion manuelle de la mémoire, pointeurs invalides, fuites, syntaxe complexe et messages d’erreur liés aux templates deviennent des critiques récurrentes.

C++11 et la naissance du « C++ moderne »

Le tournant suivant arrive en 2011. C++11 est suffisamment important pour que l’on parle couramment de modern C++.

Le standard introduit ou généralise notamment :

  • les lambdas ;
  • auto pour l’inférence de type ;
  • nullptr ;
  • les boucles for sur intervalle ;
  • les smart pointers standard ;
  • les rvalue references et la move semantics ;
  • constexpr ;
  • les variadic templates ;
  • de meilleurs outils de concurrence.

Ces fonctionnalités ne servent pas seulement à raccourcir le code. Elles modifient les pratiques recommandées.

La move semantics, par exemple, permet de transférer les ressources d’un objet devenu inutile au lieu de les recopier. Les smart pointers comme std::unique_ptr ou std::shared_ptr, combinés à RAII, permettent d’exprimer plus clairement la propriété et la durée de vie des objets.

Le C++ moderne cherche ainsi moins à demander au programmeur de gérer manuellement chaque ressource qu’à lui fournir des abstractions dont la durée de vie et le coût restent maîtrisables.

Un rythme d’évolution plus régulier

Après C++11, le langage adopte un cycle de standardisation d’environ trois ans.

C++14 consolide de nombreux éléments de C++11. C++17 apporte notamment std::optional, std::variant, std::filesystem et de nouvelles possibilités de programmation générique.

C++20 constitue un autre jalon majeur avec les concepts, les ranges, les coroutines et les modules. Les concepts permettent d’exprimer plus directement les contraintes imposées aux paramètres génériques ; les ranges rendent de nombreux traitements de séquences plus composables ; les coroutines offrent une base pour certains modèles asynchrones ; les modules visent notamment à améliorer l’organisation et la compilation par rapport au modèle historique des fichiers d’en-tête.

C++23 poursuit cette évolution en enrichissant la bibliothèque et plusieurs mécanismes du langage. Le principe général reste le même : moderniser C++ sans imposer une rupture brutale avec son immense écosystème existant.

Pourquoi C++ reste-t-il complexe ?

La complexité de C++ a plusieurs causes qui se renforcent mutuellement.

Le langage conserve une forte compatibilité historique. Il autorise plusieurs paradigmes. Il expose des détails de représentation et de durée de vie que d’autres environnements masquent. Il doit fonctionner aussi bien dans des logiciels applicatifs que dans des systèmes où quelques octets, quelques microsecondes ou l’absence de runtime imposé comptent réellement.

Cette liberté signifie aussi qu’il existe souvent plusieurs façons de résoudre le même problème. Du C++ ancien, du C++ moderne et du code inspiré directement de C peuvent cohabiter dans un même projet.

Les guides de bonnes pratiques et les bibliothèques modernes cherchent donc à réduire la partie dangereuse de l’espace des possibilités : conteneurs standard plutôt que tableaux manuels lorsque c’est pertinent, RAII pour les ressources, smart pointers lorsque la propriété dynamique l’exige, algorithmes et types expressifs plutôt que gestion manuelle répétitive.

C++, Java et les compromis de conception

L’apparition de Java dans les années 1990 illustre une autre réponse à certains problèmes rencontrés par les développeurs C++. Java conserve une syntaxe familière mais s’appuie sur une machine virtuelle et un ramasse-miettes, en limitant plusieurs mécanismes de bas niveau.

C++ privilégie davantage le contrôle de la représentation, la gestion déterministe des ressources et l’absence de coût imposé pour des fonctionnalités non utilisées. Java accepte un environnement d’exécution plus structurant en échange d’un modèle plus uniforme.

Il ne s’agit pas de déterminer quel choix est universellement supérieur : les deux langages répondent à des contraintes différentes. L’histoire de Java permet de comparer ces trajectoires.

Où C++ reste essentiel

Malgré l’apparition de nombreux concurrents, C++ conserve une place majeure lorsque performance, latence, contrôle mémoire, portabilité native ou accès au matériel sont importants.

On le retrouve notamment dans les moteurs de jeux, navigateurs, bases de données, outils de création, calcul scientifique, systèmes embarqués, infrastructures à faible latence et nombreuses bibliothèques utilisées depuis d’autres langages.

Son ancienneté constitue ici une force autant qu’une contrainte. Des décennies de compilateurs, bibliothèques, expertise et code industriel forment un écosystème difficile à remplacer d’un bloc.

De nouveaux langages, notamment Rust, proposent d’autres compromis autour de la sécurité mémoire et de la programmation système. Ils peuvent concurrencer C++ dans certains domaines sans rendre pour autant son immense base logicielle obsolète.

Ce que l’histoire de C++ révèle

C++ n’a pas suivi une trajectoire simple allant d’un langage ancien vers un langage entièrement redessiné. Il s’est développé par couches successives : C with Classes, orientation objet, templates, STL, standardisation, C++ moderne, puis cycles réguliers d’évolution.

Certaines de ces couches compliquent le langage. D’autres permettent précisément de remplacer d’anciennes pratiques par des abstractions plus sûres et plus expressives sans perdre les propriétés qui intéressent ses utilisateurs.

Sa longévité repose donc sur un équilibre inhabituel : changer suffisamment pour rester pertinent, mais pas au point de rompre avec le monde qu’il équipe déjà.

Chronologie

  • 1979 : Bjarne Stroustrup commence C with Classes aux Bell Labs.
  • 1983 : le langage prend le nom C++.
  • 1985 : première édition de The C++ Programming Language et première diffusion commerciale.
  • Fin des années 1980–1990 : développement des templates et de la programmation générique.
  • Années 1990 : la STL d’Alexander Stepanov est intégrée au processus de standardisation.
  • 1998 : publication de la première norme ISO, C++98.
  • 2003 : révision corrective C++03.
  • 2011 : C++11 ouvre l’ère du C++ moderne.
  • 2014 : C++14.
  • 2017 : C++17.
  • 2020 : C++20 introduit notamment concepts, ranges, coroutines et modules.
  • 2023 : C++23 poursuit l’évolution du langage et de sa bibliothèque.
  • Aujourd’hui : C++ continue d’évoluer par le processus de standardisation ISO tout en restant largement utilisé dans les logiciels sensibles aux performances.

Questions fréquentes

C++ est-il simplement une version orientée objet de C ?

Non. L’orienté objet a joué un rôle majeur dans ses débuts, mais les templates, la STL, RAII et la programmation générique sont devenus tout aussi structurants. C++ est aujourd’hui un langage multiparadigme.

Pourquoi C++ reste-t-il compatible avec C ?

C++ a été conçu comme une évolution pragmatique de C et a bénéficié de son écosystème. Cette continuité a facilité son adoption. La compatibilité n’est toutefois pas absolue : un programme C valide n’est pas nécessairement un programme C++ valide.

Qu’est-ce que le C++ moderne ?

L’expression désigne généralement les pratiques et fonctionnalités introduites à partir de C++11 : RAII systématique, conteneurs et algorithmes standard, smart pointers, move semantics, lambdas et autres outils destinés à écrire du code plus expressif et plus sûr.

Pourquoi C++ n’utilise-t-il pas un ramasse-miettes obligatoire ?

Le langage privilégie un contrôle déterministe des ressources et ne veut pas imposer un runtime ou un coût de collecte à tous les programmes. RAII, les conteneurs et les smart pointers permettent d’automatiser une grande partie de la gestion des ressources sans garbage collector obligatoire.

C++ est-il encore pertinent face à Rust et aux langages plus récents ?

Oui, notamment grâce à son écosystème, ses performances, sa portabilité native et l’énorme quantité de logiciels existants. Rust propose des garanties de sécurité mémoire différentes et constitue une alternative importante dans certains nouveaux projets, mais les deux langages coexistent aujourd’hui dans de nombreux domaines.

Pourquoi C++ évolue-t-il sans supprimer davantage d’anciennes fonctionnalités ?

Parce que la compatibilité avec plusieurs décennies de code est une valeur majeure de son écosystème. Le comité préfère souvent ajouter de meilleurs mécanismes et faire évoluer les pratiques plutôt que rendre brutalement incompatibles de vastes bases de code.

Cet article vous a-t-il été utile ?

Sources et références

Collection

Langages de programmation

9 / 26

  1. 01Grace Hopper : des premiers compilateurs à COBOL
  2. 02John Backus : FORTRAN, la notation BNF et le refus du code machine
  3. 03Dennis Ritchie : le langage C au cœur d'Unix
  4. 04FORTRAN : prouver qu'un compilateur peut rivaliser avec l'assembleur
  5. 05Le langage C : rendre les systèmes portables sans masquer la machine
  6. 06Niklaus Wirth : de Pascal à Oberon, concevoir par la simplicité
  7. 07Bjarne Stroustrup : concevoir C++ sans renoncer aux performances
  8. 08Pascal : apprendre à programmer en rendant la structure visible
  9. 09C++ : de C with Classes au C++ moderne
  10. 10La programmation orientée objet : objets, messages et abstractions réutilisables
  11. 11Guido van Rossum : créer Python pour rendre le code lisible
  12. 12Brendan Eich : JavaScript, du prototype de Netscape au standard du Web
  13. 13James Gosling : l'ingénieur à l'origine de Java
  14. 14Python : la lisibilité, les batteries incluses et un écosystème mondial
  15. 15Java : écrire une fois, exécuter partout
  16. 16JavaScript : le langage qui a rendu le Web interactif
  17. 17Ken Thompson : d’Unix au langage Go, la simplicité comme méthode
  18. 18John McCarthy : Lisp et l’idée de programmer avec des symboles
  19. 19Alan Kay : Smalltalk et l’ordinateur comme média personnel
  20. 20Barbara Liskov : l'abstraction qui a rendu le logiciel modulaire
  21. 21Robin Milner : ML, la preuve assistée et les langages de l’interaction
  22. 22Brian Kernighan : AWK, Unix et l'art d'expliquer le code
  23. 23Anders Hejlsberg : de Turbo Pascal à C# et TypeScript
  24. 24Larry Wall : Perl, le langage qui a relié les outils d'Internet
  25. 25Yukihiro Matsumoto : Ruby et le bonheur du programmeur
  26. 26Rasmus Lerdorf : PHP et la démocratisation du Web dynamique
BiographieHistoire de l’informatiqueDébutant

James Gosling : l'ingénieur à l'origine de Java

Comment James Gosling et l'équipe Green de Sun ont conçu Java : d'Oak aux machines virtuelles, de la portabilité promise à l'héritage du langage.

17 août 20268 min