Modes d'héritage en C++ : public, private, protected

L'héritage en C++ permet à une classe de dériver des propriétés et des comportements d'une autre classe. Les trois principaux modes d'héritage sont public, private et protected, chacun influençant la visibiltié des membres de la classe de base dans la classe dérivée.

Héritage Public Dans l'héritage public, les membres publics de la classe de base restent publics dans la classe dérivée, et les membres protégés de la classe de base restent protégés. Les membres privés de la classe de base ne sont jamais directement accessibles par la classe dérivée ou ses descendants.

Héritage Private Avec l'héritage privé, les membres publics et protégés de la classe de base deviennent privés dans la classe dérivée. Ils ne sont donc pas accessibles directement depuis l'extérieur de la classe dérivée, ni par les classes qui en dérivent ultérieurement. Les membres privés de la classe de base restent inaccessibles.

Héritage Protected L'héritage protégé rend les membres publics et protégés de la classe de base protégés dans la classe dérivée. Ces membres sont accessibles aux membres de la classe dérivée et à leurs descendants, mais pas directement depuis l'extérieur de la hiérarchie d'héritage. Les membres privés de la classe de base restent inaccessibles.

Le tableau suivant résume la visibilité des membres de la classe de base dans la classe dérivée pour chaque type d'héritage :

Membre de la classe de base Héritage Public Héritage Private Héritage Protected
Public Public Private Protected
Protected Protected Private Protected
Private Inaccessible Inaccessible Inaccessible

Il est crucial de distinguer l'accessibilité des membres pour les objets de la classe dérivée par rapport à l'accessibilité pour les fonctions membres de la classe dérivée.

Considérons la classe de base BaseClass avec des membres privateMember, protectedMember, et publicMember.

#include <iostream>

class BaseClass {
private:
    int privateMember = 1;
protected:
    int protectedMember = 2;
public:
    int publicMember = 3;
};

Examinons maintenant les classes dérivées :

Classe DerivedPublic (Héritage Public) Les membres publics de BaseClass restent publics, et les membres protégés restent protégés.

class DerivedPublic : public BaseClass {
public:
    void accessBaseMembers() {
        // int access1 = privateMember; // Erreur: privateMember est inaccessible
        int access2 = protectedMember; // OK: protectedMember est protected dans DerivedPublic
        int access3 = publicMember;    // OK: publicMember est public dans DerivedPublic
        std::cout << "Access within DerivedPublic (public inheritance): "
                  << access2 << ", " << access3 << std::endl;
    }
};

Un objet de DerivedPublic peut accéder à publicMember, mais pas à protectedMember ou privateMember.

Classe DerivedPrivate (Héritage Private) Les membres publics et protégés de BaseClass deviennent privés dans DerivedPrivate.

class DerivedPrivate : private BaseClass {
public:
    void accessBaseMembers() {
        // int access1 = privateMember; // Erreur: privateMember est inaccessible
        int access2 = protectedMember; // OK: protectedMember est private dans DerivedPrivate
        int access3 = publicMember;    // OK: publicMember est private dans DerivedPrivate
        std::cout << "Access within DerivedPrivate (private inheritance): "
                  << access2 << ", " << access3 << std::endl;
    }
};

Un objet de DerivedPrivate ne peut accéder à aucun membre de BaseClass directement.

Classe DerivedProtected (Héritage Protected) Les membres publics et protégés de BaseClass deviennent protégés dans DerivedProtected.

class DerivedProtected : protected BaseClass {
public:
    void accessBaseMembers() {
        // int access1 = privateMember; // Erreur: privateMember est inaccessible
        int access2 = protectedMember; // OK: protectedMember est protected dans DerivedProtected
        int access3 = publicMember;    // OK: publicMember est protected dans DerivedProtected
        std::cout << "Access within DerivedProtected (protected inheritance): "
                  << access2 << ", " << access3 << std::endl;
    }
};

Un objet de DerivedProtected ne peut accéder à aucun membre de BaseClass directement.

L'exemple de code suivant illustre ces concepts :

#include <iostream>

class Grandparent {
private:
    int privateGrand = 10;
protected:
    int protectedGrand = 20;
public:
    int publicGrand = 30;
};

class ParentPublic : public Grandparent {
public:
    void showPublic() {
        // privateGrand = 1; // Erreur
        protectedGrand = 2; // OK
        publicGrand = 3;    // OK
        std::cout << "ParentPublic: " << protectedGrand << ", " << publicGrand << std::endl;
    }
};

class ParentPrivate : private Grandparent {
public:
    void showPrivate() {
        // privateGrand = 1; // Erreur
        protectedGrand = 2; // OK (private dans ParentPrivate)
        publicGrand = 3;    // OK (private dans ParentPrivate)
        std::cout << "ParentPrivate: " << protectedGrand << ", " << publicGrand << std::endl;
    }
};

class ParentProtected : protected Grandparent {
public:
    void showProtected() {
        // privateGrand = 1; // Erreur
        protectedGrand = 2; // OK (protected dans ParentProtected)
        publicGrand = 3;    // OK (protected dans ParentProtected)
        std::cout << "ParentProtected: " << protectedGrand << ", " << publicGrand << std::endl;
    }
};

class ChildPublic : public ParentPublic {
public:
    void accessGrandparent() {
        // Cannot access privateGrand directly
        protectedGrand = 22; // OK: inherited as protected from ParentPublic
        publicGrand = 33;    // OK: inherited as public from ParentPublic
        std::cout << "ChildPublic accessing ParentPublic members: " << protectedGrand << ", " << publicGrand << std::endl;
    }
};

class ChildPrivate : private ParentPrivate {
public:
    void accessGrandparent() {
        // Cannot access privateGrand directly
        // protectedGrand = 22; // Erreur: protectedGrand est private dans ParentPrivate
        // publicGrand = 33;    // Erreur: publicGrand est private dans ParentPrivate
        // To access, ParentPrivate would need a public/protected method.
    }
};

class ChildProtected : protected ParentProtected {
public:
    void accessGrandparent() {
        // Cannot access privateGrand directly
        protectedGrand = 22; // OK: inherited as protected from ParentProtected
        publicGrand = 33;    // OK: inherited as protected from ParentProtected
        std::cout << "ChildProtected accessing ParentProtected members: " << protectedGrand << ", " << publicGrand << std::endl;
    }
};

int main() {
    ParentPublic objPub;
    objPub.showPublic();
    // objPub.protectedGrand = 22; // Erreur: protected
    // objPub.publicGrand = 33;    // OK: public

    ParentPrivate objPriv;
    objPriv.showPrivate();
    // objPriv.protectedGrand = 22; // Erreur: private
    // objPriv.publicGrand = 33;    // Erreur: private

    ParentProtected objProt;
    objProt.showProtected();
    // objProt.protectedGrand = 22; // Erreur: protected
    // objProt.publicGrand = 33;    // Erreur: protected

    ChildPublic childPub;
    childPub.showPublic(); // Inherited from ParentPublic
    childPub.accessGrandparent(); // Accessing grandparent members via ParentPublic

    ChildPrivate childPriv;
    // childPriv.showPrivate(); // Erreur: showPrivate is private in ChildPrivate

    ChildProtected childProt;
    childProt.showProtected(); // Inherited from ParentProtected
    childProt.accessGrandparent(); // Accessing grandparent members via ParentProtected

    return 0;
}

Étiquettes: C++ Héritage public private protected

Publié le 2 juillet à 16h31