Poss0502 slides

377 views
289 views

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
377
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
4
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Poss0502 slides

  1. 1. Techniques dimplémentation de la POO en C++ statique Le paradigme objet et le C++
  2. 2. Techniques dimplémentation de la POO en C++ statique Classes, objets et messages dénition dune classe envoi de message : convention dappel messages reconnus : réception de message : implémentation des mé- déclaration des méthodes thodes
  3. 3. Techniques dimplémentation de la POO en C++ statiquePour la modélisation suivante : On écrit traditionnellement : ¤ class Cow { Cow public : // `Cow objects can receive // ` eat messages with an // argument of type ` Food +eat(Food) } void eat(Food);
  4. 4. Techniques dimplémentation de la POO en C++ statique Envoi dun message : Réception par une méthode : ¤ void Cow::eat(Food f) ¤ // send message `eat { // to object ` cow, cout Moo, I like that // with argument ` grass f endl ; cow . eat ( grass ); }
  5. 5. Techniques dimplémentation de la POO en C++ statique Héritage et polymorphisme dénition dune relation dhé- voir comme : ritage références et coercion polymorphisme dhéritage : liaison retardée : agir sur une référence vers méthodes virtuelles une classe de base
  6. 6. Techniques dimplémentation de la POO en C++ statiquePour la modélisation suivante : On écrit traditionnellement : ¤ class Herbivor { public : virtual void eat(Food) = 0; }; class Cow : public Herbivor { public : Herbivor void eat(Food); +eat(Food) } class Sheep : public Herbivor { public : Cow Sheep void eat(Food); +eat(Food) +eat(Food) }
  7. 7. Techniques dimplémentation de la POO en C++ statique Démonstration de la liaison Alorithme polymorphe : ¤ retardée : void Farmer:: feed( Herbivor thingy) ¤ // ` thingy is a reference to { // an object of base class Grass g; // ` Herbivor thingy . eat(g); } thingy . eat ( grass ); // [...] farmer . feed(cow); farmer . feed(sheep ); // [...] Lappel est résolu par liaison retardée.
  8. 8. Techniques dimplémentation de la POO en C++ statique Mais... 1 invocation dune méthode les règles de typage im- virtuelle ⇒ 1 indirection pour posent une coercion dangeu- obtenir son adresse avant reuse pour des cas de modé- lappel lisation courants le compilateur na pas la pos- on voudrait des types vir- sibilité dinliner les méthodes tuels
  9. 9. Techniques dimplémentation de la POO en C++ statique Objectifs : Moyens mis en ÷uvre : résoudre statiquement la liai- la méta-programmation son retardée le polymorphisme paramé- conserver, si possible, le trique sucre syntaxique du C++ ⇒ utiliser les templates du le code doit exprimer la mo- C++ pour faire de la délisation théorique Méta-POO
  10. 10. Techniques dimplémentation de la POO en C++ statique Première approche et introduction aux techniques
  11. 11. Techniques dimplémentation de la POO en C++ statique Objectif : instruire la classe de base. Première modélisation : Implémentation : ¤ templatetypename Exact class Herbivor SubClass { Herbivor public : void eat(Food); } ¤ templatetypename Exact HerbivorCow void HerbivorExact::eat(Food f) { // emulate method dispatching // with controlled coercion Cow static_castExact∗(this)−eat(f); } ¤ HerbivorSheep class Cow : public HerbivorCow { /∗ no change ∗/ } class Sheep : public HerbivorSheep Sheep { /∗ no change ∗/ }
  12. 12. Techniques dimplémentation de la POO en C++ statique Héritage statique : polymorphisme dhéritage par le polymorphisme paramétrique contraint. Lalgorithme polymorphe : ... devient : ¤ templatetypename Any ¤void Farmer:: feed( Herbivor thingy) void Farmer:: feed( HerbivorAny thingy){ { Grass g; Grass h; thingy . eat(g); thingy . eat(g);} }
  13. 13. Techniques dimplémentation de la POO en C++ statique Avantages : Inconvénients : mécanismes syntaxiques non idiomatiques lexpression des implémenta- templates longs à compiler tion nest pas modiée multiplication cartésienne des on conserve la modélisation instances : le compilateur peut inliner (classesf illes) × (classesmeres)
  14. 14. Techniques dimplémentation de la POO en C++ statique Le code classique : Le code statique : ¤ templatetypename Exact struct IntFunc { ¤ int apply( int x)struct IntFunc { return dispatch (apply )(x ); }{ // dispatch is a macro virtual int apply( int x) = 0; };}; struct Annulate : IntFuncAnnulatestruct Annulate : IntFunc {{ int apply( int x) int apply( int x) { return 0; } { return 0; } };}; templatetypename Anyvoid many_applies(const unsigned N, void many_applies(const unsigned N, IntFunc f, IntFuncAny f, int x) int x){ { for (unsigned i = 0; i N; ++i) for (unsigned i = 0; i N; ++i) f . apply(x ); f . apply(x );}; };
  15. 15. Techniques dimplémentation de la POO en C++ statique Après optimisation par GCC : 7 classic paradigm static paradigm 6 5 iteration time, in seconds 4 3 2 1 0 0 2e+07 4e+07 6e+07 8e+07 1e+08 N
  16. 16. Techniques dimplémentation de la POO en C++ statique Les vaches mangent de lherbe...
  17. 17. Techniques dimplémentation de la POO en C++ statique ... alias la contravariance des arguments. Food Implémentation classique : ¤ struct Food { /∗ ... ∗/ }; struct Grass : Food { /∗ ... ∗/ }; struct Animal Grass { virtual void eat(Food) = 0; }; struct Cow : Animal Animal { // declaring eat(Grass) violates +eat(Food) // the contravariance void eat(Food f) { // not safe , not ecient : Grass g = dynamic_castGrass(f); Cow /∗ ... ∗/ } +eat(Grass) };
  18. 18. Techniques dimplémentation de la POO en C++ statique en utilisant lhéritage statique, ce code devient... dune part : et dautre part : ¤ templatetypename SubClass struct Animal { templatetypename F void eat(FoodF f) { dispatch (eat)( static_castF(f)); } }; struct Cow : AnimalCow ¤{templatetypename SubClass void eat(Grass g)struct Food {{ /∗ ... ∗/ }; cout Moo, I love grass. endl ;struct Grass : FoodGrass }{ /∗ ... ∗/ }; }; Cette version est correctement typée !
  19. 19. Techniques dimplémentation de la POO en C++ statique Le compilateur rejette eectivement les cas invalides : ¤ /∗ ... ∗/Meat m;AnimalCow a = cow;a . eat(m); donne : ¤contra .cc : In member function ` void AnimalSubClass::eat(FoodAny) [ with Any = Meat, SubClass = Cow]:contra .cc :35: instantiated from ` void feed(AnimalAnyAnimal, FoodAnyFood) [with AnyAnimal = Cow, AnyFood = Meat]contra .cc :44: instantiated from herecontra .cc :18: no matching function for call to ` Cow::eat(Meat)contra .cc :26: candidates are : void Cow::eat(Grass)
  20. 20. Techniques dimplémentation de la POO en C++ statique Séparation interface/dénition, classes abstraites
  21. 21. Techniques dimplémentation de la POO en C++ statique Ce code nest pas correct : ¤ Celui-ci lest :templatetypename Exact ¤struct BaseClass templatetypename Exact{ struct BaseClass void m() { { void m() // dispatch to Exact :: m { static_castExact∗(this) // dispatch to Exact :: m_impl −m(); static_castExact∗(this) } −m_impl();}; } };struct Deriv : BaseClassDeriv{ /∗ m not implemented ∗/}; ⇒ le compilateur peut détecter ⇒ au lieu dun message derreur, le loubli dimplémentation dans la compilateur génère une récursion innie. classe dérivée. Deux eets : un problème corrigé et une séparation de noms entre interface et implémentation.
  22. 22. Techniques dimplémentation de la POO en C++ statique Ce code nest pas correct : ¤ Celui-ci lest : ¤templatetypename Exact templatetypename Exactstruct AbstractClass struct AbstractClass{ { void m(); void m();}; protected:// [...] ~AbstractClass (); AbstractClass Foo foo; };// [...]⇒ le compilateur permet dinstancier ⇒ le compilateur interdit une classe abstraite linstanciation de la classe On simule les classes abstraites en protégeant le destructeur.
  23. 23. Techniques dimplémentation de la POO en C++ statique Ajout de niveaux de hiérarchie supplémentaires
  24. 24. Techniques dimplémentation de la POO en C++ statique Pour la hiérarchie suivante : On peut pratiquer trois méthodes : Méthode R Animal +eat(Food) ⇒ la classe de base connaît la classe immédiatement infé- Herbivor +eat(Grass) rieure Méthodes S1 et S2 Cow Sheep ⇒ la classe de base connaît le +eat(Grass) +eat(Grass) type exact
  25. 25. Techniques dimplémentation de la POO en C++ statique La méthode R dhéritage statique
  26. 26. Techniques dimplémentation de la POO en C++ statique Avec la méthode R, on indique à chaque dérivation le type dérivé à la classe-mère : Herbivor_Cow_Inf Inf Animal_ +eat(FoodAny) Inf #~Animal_() Cow_ +eat(GrassAny) Animal_Herbivor_Inf Herbivor_Sheep_Inf Inf Herbivor_ Inf +eat(GrassAny) Sheep_ #~Herbivor_() +eat(GrassAny)
  27. 27. Techniques dimplémentation de la POO en C++ statique Pour instancier une classe, on utilise un type bottom (⊥) : ¤ ¤typedef Cow_bottom Cow; typedef Sheep_bottom Sheep; Animal_Herbivor_Cow_bottom Animal_Herbivor_Sheep_bottom Herbivor_Cow_bottom Herbivor_Sheep_bottom Cow = Cow_bottom Sheep = Sheep_bottom
  28. 28. Techniques dimplémentation de la POO en C++ statique Le type exact de nimporte quel objet peut être retrouvé à la compilation :find exact (C) = C si inferior (C) = ⊥ find exact ( inferior (C) ) sinon. Cette formule est implémentée par templates récursifs.
  29. 29. Techniques dimplémentation de la POO en C++ statique la méthode R Avantages : Inconvénients : le type des classes donne des les messages derreur de ty- informations sur la hiérarchie page sont très complexes linstanciation des classes limplémentation de find exact terminales est facile à est coûteuse en temps de laide de ⊥ compilation
  30. 30. Techniques dimplémentation de la POO en C++ statique La méthode S1 dhéritage statique
  31. 31. Techniques dimplémentation de la POO en C++ statiqueAvec la méthode S1, on indique à chaque instanciation le type exact à la hiérarchie : Exact Herbivor_Exact Animal_ +eat(FoodAny) #~Animal_() Exact Cow_ +eat(GrassAny) Animal_Exact Herbivor_Exact Exact Herbivor_ Exact +eat(GrassAny) Sheep_ #~Herbivor_() +eat(GrassAny)
  32. 32. Techniques dimplémentation de la POO en C++ statique Pour instancier une classe de la hiérarchie, il faut la dériver : ¤ ¤class Cow : public Cow_Cow class Sheep : public Sheep_Sheep{ /∗ ... ∗/ } { /∗ ... ∗/ } Animal_Cow Animal_Sheep Herbivor_Cow Herbivor_Sheep Cow_Cow Sheep_Sheep Cow Sheep
  33. 33. Techniques dimplémentation de la POO en C++ statique En C++, les constructeurs ne sont pas hérités : ¤ ¤templatetypename Exact class Cow : public Cow_Cowclass Cow_ : public Herbivor_Exact {{ public :public : templatetypename Any templatetypename Any Cow(Cow_Any mother, Cow_(Cow_Any mother, Cow_Any father) Cow_Any father) /∗ dispatch to parent class ∗/ { /∗ birth code ∗/ } : Cow_Cow(mother, father) {} // ...} } Le(s) constructeur(s) doivent être recopiés à la dérivation.
  34. 34. Techniques dimplémentation de la POO en C++ statique la méthode S1 Avantages : Inconvénients : la création dun type ins- pas de coût pour retrouver le tanciable implique la création type exact dans la classe de dune nouvelle classe base le compilateur nempêche pas les messages derreur de de dériver une classe abstraite typage sont (relativement) de la hiérarchie pour créer un simples type instanciable
  35. 35. Techniques dimplémentation de la POO en C++ statique La méthode S2 dhéritage statique
  36. 36. Techniques dimplémentation de la POO en C++ statique Avec la méthode S2, on indique à chaque instanciation un traits vers le type exact à la hiérarchie : ExactFinder Animal_ Herbivor_ExactFinder +Exact = ExactFinder::ret +eat(FoodAny) ExactFinder #~Animal_() Cow_ +eat(GrassAny) Animal_ExactFinder Herbivor_ExactFinder ExactFinder Herbivor_ +eat(GrassAny) ExactFinder #~Herbivor_() Sheep_ +eat(GrassAny)
  37. 37. Techniques dimplémentation de la POO en C++ statiquePour instancier une classe, il faut construire les traits adéquats : ¤ ¤struct IsCow struct IsSheep{ { typedef Cow_IsCow ret; typedef Sheep_IsSheep ret;}; };typedef IsCow:: ret Cow; typedef IsSheep :: ret Sheep; IsCow +ret = Cow_IsCow IsSheep +ret = Sheep_IsSheep Animal_IsCow Animal_IsSheep Herbivor_IsCow Herbivor_IsSheep Cow = Cow_IsCow Sheep = Sheep_IsSheep
  38. 38. Techniques dimplémentation de la POO en C++ statique On peut même automatiser la création de ExactFinder : T:template class class Make +ret = TMakeT Cow = MakeCow_::ret Sheep = MakeSheep_::ret ¤templatetemplateclass class Tstruct Make{ typedef TMakeT ret;};typedef MakeSheep_::ret Sheep;typedef MakeCow_::ret Cow;
  39. 39. Techniques dimplémentation de la POO en C++ statique Si une classe de la hiérarchie est plus paramétrée, il faut agrandir Make : T:templateclass,class class Arg1 Make1 +ret = TMake1T, Arg1, Arg1 T:templateclass,class,class class Arg1 Arg2 Make2 +ret = TMake2T, Arg1, Arg2, Arg1, Arg2
  40. 40. Techniques dimplémentation de la POO en C++ statique la méthode S2 Avantages : Inconvénients : pas de coût pour retrouver le les messages derreurs de type exact dans la classe de typage sont moins simples base quavec la méthode S1 la création dun type instan- on ne peut pas entièrement ciable est plus simple quavec automatiser la création du la méthode S1 ExactFinder
  41. 41. Techniques dimplémentation de la POO en C++ statique Un détour chez les types virtuels
  42. 42. Techniques dimplémentation de la POO en C++ statique Objectifs : Mais... équipper les hiérarchies avec le typage du C++ empêche les types virtuels une implémentation triviale garder une approche systé- la sémantique des types vir- matique de lhéritage statique tuels est encore mal dénie
  43. 43. Techniques dimplémentation de la POO en C++ statique Modélisation souhaitée : T Container +iterator: virtual type +begin(): iterator +end(): iterator +contains(T): bool T T List Vector +iterator = list_iteratorT +iterator = vector_iteratorT +begin(): list_iteratorT +begin(): vector_iteratorT +end(): list_iteratorT +end(): vector_iteratorT +contains(T): bool +contains(T): bool
  44. 44. Techniques dimplémentation de la POO en C++ statique Avec héritage statique : Container_exact_of(List, X, T) X T Container_ X T +Exact = to_exact(X) List_ +iterator = virtual_type(Exact, iterator) +begin(): iterator +iterator = list_iteratorT +end(): iterator +begin(): list_iteratorT +contains(T): bool +end(): list_iteratorT #~Container() +contains(T): bool to exact et exact of dépendent de la méthode dhéritage virtual type reste à dénir
  45. 45. Techniques dimplémentation de la POO en C++ statique Une implémentation triviale... ¤#dene virtual_type(ExactType, Name) typename ExactType::Nametemplatetypename Exact, typename Tstruct Container_{ typedef virtual_type (Exact, iterator ) iterator ; iterator begin() { return dispatch (begin )(); } // ...};templatetypename Exact, typename Tstruct List_ : Container_Exact, T{ typedef list_iterator T iterator; // dened elsewhere iterator begin_impl() { /∗ ... ∗/ } // ...};// derivation to instanciate the classtemplatetypename T struct List : List_ListT, T {};
  46. 46. Techniques dimplémentation de la POO en C++ statique ... ne fonctionne pas : ¤// [...] List int l; // line 36 List int:: iterator i = l . begin ();// [...] donne à la compilation : ¤triv_vt .cc : In instantiation of ` Container_Listint, int:triv_vt .cc :36: instantiated from `List_Listint, inttriv_vt .cc :36: instantiated from ` List inttriv_vt .cc :36: instantiated from heretriv_vt .cc :9: no type named ` iterator in ` struct List inttriv_vt .cc :12: no type named ` iterator in ` struct List int À linstanciation de Container , la dénition du type nest pas encore connue.
  47. 47. Techniques dimplémentation de la POO en C++ statique Pour résoudre le problème, on doit séparer la dénition des types virtuels de la hiérarchie statique. Avec les méthodes R et S1, Avec la méthode S2, on peut soit : recourir à une hiérarchie on a recours à une hiérarchie parallèle faire porter les types vir- de traits parallèle tuels par le ExactFinder
  48. 48. Techniques dimplémentation de la POO en C++ statique Avec une hiérarchie parallèle, on obtient la modélisation suivante : X T Container +Exact = to_exact(X) +iterator = vt_traitExact::iterator Container_exact_of(List, X, T) vt_traitContainer_... X X T T vt_traitList_... List_ +iterator = list_iteratorT dépend de la méthode d’héritage
  49. 49. Techniques dimplémentation de la POO en C++ statiqueIl ny a quun traits, mais ses spécialisations sont hiérarchisées : Exact vt_traitAnimalExact Ce mécanisme est nécessaire pour pouvoir dénir les types Exact virtuels à des niveaux vt_traitHerbivor_Exact intermédiaires de la hiérarchie +FoodType = Grass Exact vt_traitCow_Exact
  50. 50. Techniques dimplémentation de la POO en C++ statiqueAvantages de cette méthode : Inconvénients : nécessite une séparation permet dexprimer les besoins entre la dénition de la classe et celle de ses types virtuels courants on connaît mal la portée sé- application systématique mantique de cette construc- (donc automatisable) tion
  51. 51. Techniques dimplémentation de la POO en C++ statique Conclusion

×