L'HERITAGE EN C ++

Introduction : L'héritage est l'un des concepts clés de la programmation orientée objet (POO). Cela permet de créer de nouvelles classes qui héritent des propriétés et des méthodes d'une classe existante. En C++, l'héritage est mis en œuvre à l'aide de la notion de classe de base (ou classe mère) et de classe dérivée (ou classe fille).

Définition : L'héritage est un mécanisme de la POO qui permet de créer une nouvelle classe en se basant sur une classe existante. La classe existante est appelée classe de base, tandis que la nouvelle classe créée est appelée classe dérivée. La classe dérivée hérite de toutes les propriétés et méthodes de la classe de base, et peut également ajouter de nouvelles propriétés et méthodes.

Syntaxe : La syntaxe pour définir une classe dérivée en C++ est la suivante :

class ClasseDerivee : [visibilité] ClasseDeBase
{
    // Définition de la classe dérivée
};

La partie [visibilité] est facultative et peut être public, protected ou private. Si cette partie est omise, la visibilité par défaut est private.

Exemple avec la classe Point : Nous allons créer une classe Point qui représente un point dans un espace à deux dimensions. Nous allons ensuite créer une classe PointColore qui hérite de la classe Point et ajoute une couleur.


class Point
{
public:
    Point(double x, double y) { this->m_x=x; this->m_y=y; }
    double getX() const { return m_x; }
    double getY() const { return m_y; }
private:
    double m_x, m_y;
};

class PointColore : public Point
{
public:
//methodes inline
    PointColore(double x, double y, string couleur)
        : Point(x, y) { this->m_couleur=couleur; }
    string getCouleur() const { return m_couleur; }
private:
    string m_couleur;
};

Dans cet exemple, nous avons défini une classe Point avec deux méthodes getX() et getY() pour accéder aux coordonnées x et y. Nous avons ensuite défini une classe PointColore qui hérite de la classe Point et ajoute une méthode getCouleur() pour accéder à la couleur du point.

Notez que la classe Point n'a pas de constructeur par défaut, donc nous devons appeler le constructeur de la classe de base dans le constructeur de la classe dérivée en utilisant la syntaxe suivante :

PointColore(double x, double y, string couleur) { Point(x, y); this->m_couleur=couleur; }

La partie ": Point(x, y)" appelle le constructeur de la classe de base avec les arguments x et y.

Exemple avec la classe Personne : Nous allons créer une classe Personne qui représente une personne avec un nom et un prénom. Nous allons ensuite créer une classe Etudiant qui hérite de la classe Personne et ajoute un numéro d'étudiant.


class Personne
{
public:
    Personne(string nom, string prenom)
        { this->m_nom=nom;  this->m_prenom=prenom;}
    string getNom() const { return m_nom; }
    string getPrenom() const { return m_prenom; }
private:
    string m_nom, m_prenom;
};


class Etudiant : public Personne
{
public:
    Etudiant(string nom, string prenom, int numEtudiant)
        : Personne(nom, prenom) { this->m_numEtudiant=numEtudiant; }
    int getNumEtudiant() const { return m_numEtudiant; }
private:
    int m_numEtudiant;
};



La classe Etudiant est une sous-classe de la classe Personne. Elle hérite ainsi de toutes les propriétés et méthodes publiques et protégées de la classe Personne.

Dans cet exemple, la classe Etudiant possède une propriété supplémentaire m_numEtudiant qui représente le numéro d'étudiant de l'étudiant. La méthode getNumEtudiant() permet d'obtenir cette information.

Grâce à l'héritage, les instances de la classe Etudiant auront accès aux méthodes getNom() et getPrenom() définies dans la classe Personne.

Les membres m_nom et m_prenom de la classe Personne sont déclarés comme private, ce qui signifie qu'ils ne sont pas accessibles depuis l'extérieur de la classe. Cela permet d'assurer l'encapsulation des données de la classe et de limiter les effets de bord liés à la modification directe des données.

Les méthodes getNom() et getPrenom() sont déclarées comme public, ce qui signifie qu'elles sont accessibles depuis l'extérieur de la classe et qu'elles permettent d'obtenir les informations encapsulées dans les membres m_nom et m_prenom.

Enfin, la classe Etudiant est déclarée comme public lors de l'héritage de la classe Personne. Cela signifie que les membres public et protected de la classe Personne sont accessibles depuis la classe Etudiant. Les membres private de la classe Personne ne sont pas accessibles depuis la classe Etudiant.

L'héritage est un concept clé de la programmation orientée objet en C++. Il permet de définir des hiérarchies de classes et de réutiliser le code existant en l'étendant pour répondre à de nouveaux besoins. L'héritage permet également d'améliorer la lisibilité du code en organisant les classes en hiérarchies logiques et cohérentes.

 

Il existe trois types d'héritage en C++ : privé, public et protégé.

Dans le cas où les attributs de la classe mère sont privés, les classes filles ne peuvent pas accéder à ces attributs directement, même si elles en héritent. Dans ce cas, les classes filles peuvent seulement accéder aux membres publics et protégés de la classe mère.

Par exemple, considérons la classe mère "Personne" qui a un attribut privé "nom". La classe fille "Etudiant" hérite de la classe mère "Personne". Si "nom" est un attribut privé de la classe "Personne", alors la classe "Etudiant" ne peut pas accéder directement à cet attribut. Elle peut cependant utiliser une méthode publique ou protégée de la classe mère pour accéder ou modifier l'attribut.

Dans le cas où les attributs de la classe mère sont protégés, les classes filles peuvent accéder à ces attributs directement, mais uniquement dans la classe fille elle-même ou dans ses classes filles dérivées.

Par exemple, si "nom" est un attribut protégé de la classe "Personne", alors la classe "Etudiant" peut accéder directement à cet attribut dans la classe "Etudiant" ou dans une classe fille de "Etudiant".

Enfin, dans le cas où les attributs de la classe mère sont publics, les classes filles peuvent accéder à ces attributs directement, où qu'elles se trouvent.

Voici un exemple de classes "Personne" et "Etudiant" avec différents types d'héritage :

class Personne {
private:
    string nom;
protected:
    int age;
public:
    Personne(string n, int a) : { nom=n; age=a;}
    string getNom() const { return nom; }
    void setNom(string n) { nom = n; }
    int getAge() const { return age; }
    void setAge(int a) { age = a; }
};

class Etudiant : public Personne {
private:
    string niveau;
public:
    Etudiant(string n, int a, string nv) : Personne(n, a) { niveau=nv;}
    string getNiveau() const { return niveau; }
    void setNiveau(string nv) { niveau = nv; }
    void afficherInfos() const {
        cout << "Nom : " << getNom() << endl;
        cout << "Age : " << getAge() << endl;
        cout << "Niveau : " << niveau << endl;
    }
};

int main() {
    Etudiant e("Bob", 20, "Licence");
    e.setNom("Henzo"); // OK, setNom() est public
    e.age = 21; // OK, age est protégé
    e.niveau = "Master"; // OK, niveau est privé à Etudiant
    e.afficherInfos(); // OK, getNom(), getAge() et getNiveau() sont publics
    return 0;
}

Dans cet exemple, l'attribut "nom" est privé dans la classe "Personne", donc la classe "Etudiant" ne peut pas y accéder directement. Les méthodes "getNom()" et "setNom()" sont fournies pour permettre à la classe "Etudiant" d'accéder et de modifier l'attribut "nom".

L'attribut "age" est protégé dans la

classe "Personne". Cela signifie que la classe "Etudiant" peut y accéder directement, mais pas les classes qui héritent de "Etudiant". Par exemple, si une classe "Doctorant" hérite de "Etudiant", elle ne pourra pas accéder directement à l'attribut "age". Les méthodes "getAge()" et "setAge()" sont également fournies pour permettre à la classe "Etudiant" d'accéder et de modifier l'attribut "age".

En ce qui concerne les types d'héritage en C++, il y en a trois: privé, public et protégé.

L'héritage privé signifie que les membres publics et protégés de la classe de base deviennent membres privés de la classe dérivée. Cela signifie que la classe dérivée peut accéder aux membres de la classe de base, mais ils ne sont pas accessibles en dehors de la classe dérivée. Par exemple:

class A {
public:
    int x;
protected:
    int y;
private:
    int z;
};

class B : private A {
public:
    void foo() {
        x = 1; // OK
        y = 2; // OK
        z = 3; // erreur de compilation - z est privé dans A
    }
};

Dans cet exemple, la classe "B" hérite de "A" en utilisant l'héritage privé. Cela signifie que les membres publics et protégés de "A" (c'est-à-dire "x" et "y") deviennent membres privés de "B", tandis que "z" est inaccessible depuis "B". Dans la méthode "foo()", "B" peut accéder à "x" et "y", mais pas à "z".

L'héritage public signifie que les membres publics et protégés de la classe de base deviennent membres publics et protégés de la classe dérivée, respectivement. Cela signifie que la classe dérivée peut accéder aux membres de la classe de base et qu'ils sont également accessibles en dehors de la classe dérivée. Par exemple:

class A {
public:
    int x;
protected:
    int y;
private:
    int z;
};

class B : public A {
public:
    void foo() {
        x = 1; // OK
        y = 2; // OK
        z = 3; // erreur de compilation - z est privé dans A
    }
};

Dans cet exemple, la classe "B" hérite de "A" en utilisant l'héritage public. Cela signifie que les membres publics et protégés de "A" (c'est-à-dire "x" et "y") deviennent membres publics et protégés de "B", respectivement, tandis que "z" est inaccessible depuis "B". Dans la méthode "foo()", "B" peut accéder à "x" et "y", mais pas à "z".

L'héritage protégé est similaire à l'héritage public, sauf que les membres protégés de la classe de base deviennent membres protégés de la classe dérivée. Cela signifie que la classe dérivée peut accéder aux membres protégés de la classe de base, mais ils ne sont pas accessibles en dehors de la classe dérivée.

Voici un exemple pour illustrer l'héritage protégé :

class A {
protected:
    int x;
public:
    void foo() {
        cout << "x = " << x << endl;
    }
};

class B : protected A {
public:
    void bar() {
        x = 10; // Accès autorisé car x est protégé
        foo();  // Accès autorisé car foo() est héritée en protégé
    }
};

class C : public B {
public:
    void baz() {
        x = 20; // Erreur de compilation car x est protégé depuis B
        foo();  // Accès autorisé car foo() est héritée en protégé depuis A
    }
};

int main() {
    B b;
    C c;
    b.bar();
    c.baz();
    return 0;
}

Dans cet exemple, la classe "A" a un membre protégé "x" et une méthode publique "foo()" qui affiche la valeur de "x". La classe "B" hérite de "A" en utilisant l'héritage protégé, donc "x" devient protégé dans "B" et "foo()" est également héritée en protégé. La classe "C" hérite de "B" en utilisant l'héritage public.

La méthode "bar()" de la classe "B" peut accéder à "x" et appeler "foo()" car ils sont protégés et hérités en protégé. La méthode "baz()" de la classe "C" peut appeler "foo()" car elle est également héritée en protégé, mais elle ne peut pas accéder à "x" directement car il est protégé depuis "B".

En général, l'héritage public est utilisé lorsque la classe dérivée doit accéder à tous les membres publics de la classe de base, l'héritage protégé est utilisé lorsque la classe dérivée doit accéder aux membres protégés de la classe de base, et l'héritage privé est utilisé lorsque la classe dérivée n'a pas besoin d'accéder aux membres de la classe de base.

  • Aucune note. Soyez le premier à attribuer une note !

Ajouter un commentaire

Anti-spam