Projet de modélisation en C++ Séance 6 - Restructuration
1. Héritage 2. Généricité 3. Doxygen Notions abordées
Héritage Différence avec Java : héritage multiple possible Une classe C peut dériver de A et de B Les constructeurs de la/des classe(s) mère(s) ne sont pas hérités Les appeler explicitement pour construire les attributs hérités Appel aux destructeurs dans l'ordre inverse : Destructeur(s) de la/des classe(s) mère(s) après celui de la classe fille
Redéfinition de méthode La méthode d'une classe dérivée masque la méthode de la classe mère class Mere { public: void f() { } class Fille: public Mere { Utilisation : public: void f() { } void main() { Fille Fi; () Fille::f Fi.f(); // appel à () Mere::f Fi.Mere::f() // appel à
: Liaison statique Sélection d'un membre (attribut ou méthode) : déterminé statiquement à la compilation en fonction du type du pointeur ou de la référence Exemple : class Mere { public: int f() { } class Fille : public Mere { public: int f() { } void main() { Fille Fi; Mere *ptr = &Fi; int i = ptr->f() ; // Mere::f() (liaison ( statique
: Liaison dynamique Pour que la fonction appelée soit en rapport avec le type de l'objet pointé au moment de l'appel Mot-clé virtual Exemple : class Mere { public: virtual int f() { } class Fille : public Mere { public: int f() { } void main() { Fille Fi; Mere *ptr = &Fi; int i = ptr->f() ; // Fille::f() (liaison ( dynamique
Fonctions virtuelles pures Définition d'une fonction sans donner son implantation (laissée ( dérivées aux classes class Mere { public: virtual int f() = 0; class Fille : public Mere { public: int f() { } Une classe ayant une méthode virtuelle pure (classe abstraite) ne peut pas être instanciée ~ interface Java Pointeur vers classe abstraite : OK
Héritage multiple Une classe peut dériver de plusieurs classes mères, avec des accès différents aux attributs et méthodes de celles-ci Syntaxe : class A { class B { class C: public A, private B {
Héritage multiple?? main() { C x; x.c = x.d= x.b = 0; // OK x.a=0; //ERREUR : ambiguïté x.d::a = x.b::a = 0; // OK } ;
Héritage virtuel
Héritage virtuel class A { protected: int a; public: A() {cout <<"A1\n"; a=5; } A(int x) {cout<<"a2\n"; a=x;} void m1() {cout <<"m1a "<<a<<endl;} class D: public virtual A { protected: int d; public : D() : A(6){cout<<"D\n"; d=20; } void m4() {cout<<"m4d "<<a<<endl;} class B: public virtual A { protected: int b; public: B() : A(7) { cout<< "B\n"; b=30; } void m3() {cout<<"m3b "<<a<<endl;} class C: public virtual A, public B, public D { protected: int c; public: C() : A(8),B(),D() { cout<<"c\n"; c=40; } void m2() {cout <<"m2c "<<a<<endl;} main() { C xx; xx.m1();xx.m2(); xx.m3();xx.m4(); } ;
Gestion des ambiguïtés Utiliser :: Exemple : class Mere1 { public: int f() { } class Mere2 { public: int f() { } class Fille: public Mere1, Mere2 { void main () { Fille Fi; int i1 = Fi.f(); // Illégal car ambigu int i2 = Fi.Mere1::f(); // OK
Généricité Canevas décrivant une famille de composants : famille de fonctions famille de types famille de membres Les types peuvent devenir des paramètres Mot-clé template
Modèle de fonction : exemple template<int N> void f() { float tab[n]; // N ne sera fixé qu'à la compilation for (int i=0; i< N; i++) cin >> tab[i]; } L'instanciation void (*pf)()=f<100>; conduit le compilateur à générer le code : void f() { float tab[100]; for (int i=0; i< 100; i++) cin >> tab[i]; } L'instanciation f<100>() génère le même code et appelle la fonction
Modèle de classe : exemple 1 template <class A, class B> class paire { public: A a; B b; paire (A aa, B bb) : a(aa), b(bb) {} bool operator==(paire p) { return a==p.a && b==p.b; } void main() { paire<int, char> p1(1,'a') ;
Modèle de classe : exemple 2 template <typename T, int taille_max = 200> class pile { private: T* la_pile; public: typedef T value_type; pile() { la_pile = new T[taille_max]; } ~pile() { delete [] la_pile; } void main() { typedef pile< char, 26 > Alphabet; Alphabet p; // Pile de 26 caractères
Typename Indique que le mot suivant doit être considéré comme un type : template <typename T> Equivalent de class dans un template Egalement utile lorsque le type n'est pas instancié : template <class T> class pile { typedef typename T::value_type T_values; // T pas instancié => indique que T::value_type // est bien un type
Spécification de modèle On peut donner une implantation particulière pour un type particulier : template <class T> T min(t a, T b){ } return (a<b)? a : b; => spécialisation pour le type char* : template<> char* min<char*> (char *a, char *b) { } return strcmp(a,b)<0? a : b ;
Doxygen Similaire à Javadoc : production automatique de documentation à partir du code source Corollaire : celui-ci doit être bien commenté Les commentaires pris en compte sont ceux entre /** et */, ou ( possibles entre /*! et */ (d'autres styles Aussi pour C, Java, C#, Python, Formats de sortie : HTML, PDF, RTF, LaTeX, Génère automatiquement des diagrammes de classes
Doxygen : utilisation doxygen -g pour créer le fichier de configuration Doxyfile Editer et modifier ce fichier doxygen Doxyfile pour générer la doc doxygen -help pour plus de détails doxywizard pour le mode graphique (pas installé sur ( ensibm
Doxygen : exemple