1 Tableaux des objets C++ si on connaît le nombre dobjets nécessaires davance on peut utiliser des tableau dobjets dans les fonctions dusage class Personne { private : char Nom[Nmax]; char Societe[Nmax]; public : Personne(){Nom[0]=`\0`; Societe[0]=`\0`;} Personne(char*, char*); Personne(const Personne& p) void ModifSociete(char *); void SePresente(); }; Personne::Personne(const Personne& p){ strcpy(Nom,p.Nom); strcpy(Societe,p.Societe); } …. int main() { Personne * groupe=new Personne[Ngr]; // Uniquement le constructeur sans arguments! for(int i=0;i<Ngr;i++) { groupe[i].SePresente(); groupe[i].ModifSociete("ABC"); groupe[i].SePresente(); } return 0; }
23/02/ Héritage C++ Héritage simple Héritage multiple Java Héritage simple Spécialisation Héritage simple : la structure hiérarchique des classes, possibilité de dériver les uns des autres, évolutivité du code.
23/02/ Exemples Garage Véhicule CamionVoitureclasse – agrégat « container » classe-parent classes-enfants
4 Héritage simple class Vehicule{ protected : int puissance; int nbr_places; int vol_moteur; public : Vehicule(int _p=4, int _n=5, int _v=3); void Affiche() {cout<< Puissance = <<puissance<<places = <<nbr_places<<volume=<<vol_moteur;} }; Vehicule:: Vehicule(int _p=4, int _n=5, int _v=3){ puissance=_p; nbr_places=_n; vol_moteur=_v; } …. class Camion::public Vehicule { protected : int vitesse_autorisee; public : Camion(int _p=8, int _n= 4, int _vol=6, int _vit=80):Vehicule(_p,_n,_vol){vitesse_autorisée=_vit;} //Il faut définir un constructeur! void affiche() }; void Camion::affiche(){ cout<<puissance=<<puissance; cout<<nbr_places=<<nbr_places; cout<<vol_moteur=<<vol_moteur; cout<<vitesse_autorisée=<<vitesse_autorisee; }
5 Utilisation des méthodes de la classe parente (2) class Vehicule{ protected : int puissance; int nbr_places; int vol_moteur; public : Vehicule(int _p=4, int _n=5, int _v=3); void affiche() {cout<< Puissance = <<puissance<<places = <<nbr_places<<volume=<<vol_moteur;} }; Vehicule:: Vehicule(int _p=4, int _n=5, int _v=3){ puissance=_p; nbr_places=_n; vol_moteur=_v; } …. class Camion:public Vehicule { protected : int vitesse_autorisee; public : Camion(int _p=8, int _n= 4, int _vol=6, int _vit=80):Vehicule(_p,_n,_vol){vitesse_autorisée=_vit;} //Il faut définir un constructeur! void affiche() }; void Camion::affiche(){ Vehicule::affiche(); cout<<vitesse_autorisée=<<vitesse_autorisee; } //une fonction- membre dune classe dérivée nintroduit pas une surcharge, mais un masquage des fonctions homonymes héritées. // si la classe dérivée ne dispose pas de méthode appelée, la fonction executée sera alors celle de la classe ascendante la plus proche.
6 Héritage simple. Utilisation des méthodes de la classe parente class Vehicule{ protected : int puissance; int nbr_places; int vol_moteur; public : Vehicule(int _p=4, int _n=5, int _v=3); void Affiche() {cout<< Puissance = <<puissance<<places = <<nbr_places<<volume=<<vol_moteur;} }; Vehicule:: Vehicule(int _p=4, int _n=5, int _v=3){ puissance=_p; nbr_places=_n; vol_moteur=_v; } …. class Camion:public Vehicule { protected : int vitesse_autorisee; public : Camion(int _p=8, int _n= 4, int _vol=6, int _vit=80):Vehicule(_p,_n,_vol){vitesse_autorisée=_vit;} //Il faut définir un constructeur! void affiche() }; void Camion::affiche(){ Vehicule::affiche(); cout<<vitesse_autorisée=<<vitesse_autorisee; } //une fonction- membre dune classe dérivée nintroduit pas une surcharge, mais un masquage des fonctions homonymes héritées. // si la classe dérivée ne dispose pas de méthode appelée, la fonction executée sera alors celle de la classe ascendante la plus proche.
7 Héritage simple. Utilisation des méthodes de la classe parente class Carre { protected: int a; public: Carre(int _a=10){a=_a;} void affiche() {cout<<"a="<<a<<endl;} }; class Rectangle : public Carre{ protected: int b; public: Rectangle(int _a=2, int _b=3):Carre(_a){b=_b;} void Homotetie(int k){a=a*k;b=b*k;} }; class Parallelogramme : public Rectangle{ protected: float alpha; public: Parallelogramme(int _a, int _b, float _alpha): Rectangle(_a,_b){alpha=_alpha;} }; #include #include "Carre.hpp" int main(){ Carre C(2); Parallelogramme P(4,3,(float)1.57); Rectangle R(1,6); C.affiche(); P.affiche(); R.affiche(); P.Homotetie(4); P.affiche(); return 0; } (1)Résultat? (2)Affiche?
23/02/ Appel des constructeurs et des destructeurs Lors de linstanciation dun objet dune classe dérivée, les constructeurs parents sont appelés dans lordre de leur déclaration Lors de la destruction de cet objet, les destructeurs parents sont appelés mais dans lordre inverse.
9 Héritage simple. Constructeurs et destructeurs class Carre { protected: int a; public: Carre(int _a=10){a=_a;} void affiche() {cout<<"a="<<a<<endl;} }; class Rectangle : public Carre{ protected: int b; public: Rectangle(int _a=2, int _b=3):Carre(_a){b=_b;} void Homotetie(int k){a=a*k;b=b*k;} }; class Parallelogramme : public Rectangle{ protected: float alpha; public: Parallelogramme(int _a, int _b, float _alpha): Rectangle(_a,_b){alpha=_alpha;} }; #include #include "Carre.hpp" int main(){ Carre C(2); //cons. Carré Parallelogramme P(4,3,(float)1.57); //dans lordre sont appelés les //constructeurs de Carre, puis //Rectangle et enfin Parallelogramme Rectangle R(1,6); //dans lordre sont appelés les //constructeurs de Carre puis //de Rectangle C.affiche(); P.affiche(); R.affiche(); P.Homotetie(4); P.affiche(); return 0; }
10 Le constructeur par copie et lhéritage(1) (1) La classe dérivée na pas défini le constructeur par copie class Parent { protected: int a; public: Parent(int _a){a= _a;cout<<"Je construis Parent a= "<<a<<endl;} ~Parent(){cout<<" Je detruis Parent"<<endl;} }; class Enfant : public Parent { protected : int b; public : Enfant(int _a,int _b): Parent(_a){b=_b; cout<<"Je construis Enfant b= " <<b<<endl;} void aff(){cout<<"aff:a="<<a <<" b="<<b<<endl;} ~Enfant(){cout<<"Je detruis Enfant <<endl;} }; #include #include "A.h using namespace std; int main(){ Enfant e(2,3); Enfant b(e); e.aff(); b.aff(); return 0; } Resultats Je construis Parent a=2 Je construis Enfant b=3 aff:a= 2 b=3 Je detruis Enfant Je detruis parent Je detruis Enfant Je detruis parent Appel des constructeur par copie par défaut ( pour la partie Parent et pour la partie propre Enfant)
11 Le constructeur par copie et lhéritage(2) (2) La classe dérivée a défini le constructeur par copie class Parent { protected: int a; public: Parent(int _a){a= _a;cout<<"Je construis Parent a= "<<a<<endl;} ~Parent(){cout<<" Je detruis Parent"<<endl;} }; class Enfant : public Parent { protected : int b; public : Enfant(int _a,int _b): Parent(_a){b=_b; cout<<"Je construis Enfant b= " <<b<<endl;} Enfant (const Enfant &e):Parent(e){b=e.b; cout<<"Constructeur par copie Enfant"<<endl;} void aff(){cout<<"aff:a="<<a <<" b="<<b<<endl;} ~Enfant(){cout<<"Je detruis Enfant <<endl;} }; #include #include "A.h using namespace std; int main(){ Enfant e(2,3); Enfant b(e); e.aff(); b.aff(); return 0; } Resultats Je construis Parent a=2 Je construis Enfant b=3 Constructeur par copie Enfant aff:a= 2 b=3 Je detruis Enfant Je detruis parent Je detruis Enfant Je detruis parent Appel des constructeur par copie par défaut ( pour la partie Parent et celui défini pour la partie propre Enfant)
23/02/ Derivation publique et dérivation privée Statut dans AAccès par B et amies Accès par les utilisateurs de B N.Statut dans la clase dérivée en cas de nouvelle dérivation publicoui public protectedouinonprotected privatenon private class B : public A{…}
23/02/ Dérivation privée class B : private A Interdire à un utilisateur dune clase dérivée laccès aux membres publics de sa classe de base Quand est ce que cela est intéressant? -ex 1. Lorsque toutes les fonctions utiles de la classe de base sont redéfinies dans la classe dérivée. On interdit laccès aux anciennes fonctions -ex2. Les clases sont les mêmes, mais leur usage est différent.
14 La dérivation privée class Parent { protected: int a; public: Parent(int _a){a= _a;cout<<"Je construis Parent a= "<<a<<endl;} void AffCoucou(){cout<<« Coucou »<<endl; ~Parent(){cout<<" Je detruis Parent"<<endl;} }; class Enfant : private Parent { protected : int b; public : Enfant(int _a,int _b): Parent(_a){b=_b; cout<<"Je construis Enfant b= " <<b<<endl;} Enfant (Enfant &e):Parent(e){b=e.b; cout<<"Constructeur par copie Enfant"<<endl;} void aff(){cout<<"aff:a="<<a <<" b="<<b<<endl;} ~Enfant(){cout<<"Je detruis Enfant <<endl;} }; #include #include "A.h using namespace std; int main(){ Enfant e(2,3); //Enfant b(e); e.aff(); e.AffCoucou(); //b.aff(); return 0; } Erreur de compilation : cannot access public member declared in class 'Parent'
23/02/ Opérations entre classes de même famille(1) Héritage public class Carre {class Rectangle : public Carre{ } Carre C; Rectangle R; C=R; Parent=Enfant – possible, linverse – non Cette affectation entraîne une conversion R dans le type C, cest à dire on ne conserve que la donnée- membre a de R.
23/02/ Opérations entre classes de même famille. Pointeurs(2) Héritage public class Carre { class Rectangle : public Carre{ } Carre * pC; Rectangle * pR; pC=pR; - possible une conversion pR dans le type pC pR=(Rectangle *) pC; - possible uniquement avec le cast explicite