Que se cache-t-il derrière les modificateurs d'héritage en C++ ?
\n\nImaginez que vous êtes architecte. Vous avez le plan d'un "bâtiment" (classe de base), et vous voulez construire trois "maisons" différentes (classes dérivées). Une maison sera une copie exacte avec une entrée publique (public), la seconde avec une cour intérieure fermée (private), et la troisième avec un accès réservé à la famille et aux amis (protected). En C++, c'est exactement ainsi que fonctionnent les modificateurs d'héritage. Mais ce choix influence-t-il la vitesse d'exécution du programme ? Spoiler : oui et non. Découvrons comment ne pas vous tirer une balle dans le pied et optimiser votre code par la même occasion.
Cette question est l'une des plus populaires sur Stack Overflow (des dizaines de milliers de vues), et pour cause. Les débutants confondent souvent le niveau d'accès aux membres de la classe et le type d'héritage. Et les développeurs expérimentés savent qu'un choix judicieux d'héritage peut économiser des heures de débogage et même accélérer un peu le programme. Aujourd'hui sur pythonlib.ru, nous allons clore ce sujet une fois pour toutes.
\n\nLe triangle de l'héritage : public, private, protected
\n\nPour commencer, les bases. Imaginez que nous avons une classe de base Animal :
class Animal {\npublic:\n void eat() { /* ... */ }\nprotected:\n int age;\nprivate:\n std::string secretDNA;\n};\n\nVoyons maintenant comment les trois types d'héritage modifient l'accès à ces membres dans la classe dérivée Dog.
1. Héritage public — « tel quel »
\nLe type le plus courant et intuitif. Tous les niveaux d'accès restent inchangés :
\n- \n
public→public(accessible à tous) \n protected→protected(accessible aux héritiers) \n private→ inaccessible (reste dans la classe de base) \n
Utilisez-le lorsque vous voulez exprimer la relation "Dog EST-UN Animal". C'est la POO classique.
\n\n2. Héritage protected — « réservé aux initiés »
\nTous les membres publics de la classe de base deviennent protected dans la classe dérivée :
\n- \n
public→protected\n protected→protected\n private→ inaccessible \n
Nécessaire lorsque vous voulez cacher les détails d'implémentation au monde extérieur, mais autoriser l'accès aux "petits-enfants". Par exemple, la bibliothèque Boost utilise activement l'héritage protected pour ses mécanismes internes.
\n\n3. Héritage private — « à moi et à moi seul »
\nLe mode le plus strict. Tous les membres public et protected deviennent private :
\n- \n
public→private\n protected→private\n private→ inaccessible \n
C'est la relation "Dog est implémenté À TRAVERS Animal". Souvent utilisé à la place de la composition pour l'optimisation (voir ci-dessous).
\n\nPerformances : où le bât blesse-t-il ?
\n\nEt maintenant, passons à la question intrigante principale : le type d'héritage influence-t-il les performances ? En bref : directement non, mais indirectement, oui, tout à fait.
\n\nMythe : l'héritage private est plus rapide que public
\nCertains pensent que l'héritage private "supprime les vérifications inutiles". C'est faux. Les modificateurs d'accès (public, protected, private) sont un concept purement compile-time. Le compilateur les vérifie lors de la compilation et génère le même code machine. Il n'y a aucune différence à l'exécution.
Réalité : optimisation via l'optimisation de la classe de base vide (EBO)
\nC'est là que l'héritage private accélère réellement le programme ! Si la classe de base ne contient pas de données (classe vide), alors avec l'héritage public ou protected, le compilateur peut (mais n'est pas obligé) ajouter un octet supplémentaire pour l'alignement. Alors qu'avec l'héritage private, l'Empty Base Optimiz