Outils pour utilisateurs

Outils du site


lang:cpp:heritage

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
lang:cpp:heritage [2020/03/04 07:53] – [Cast vers un parent d'un héritage multiple] : déplacement vers la page cast rootlang:cpp:heritage [2020/03/10 23:07] (Version actuelle) – supprimée root
Ligne 1: Ligne 1:
-====override==== 
-Une classe enfant redéfinit une méthode du parent. Cela peut se faire avec ou sans l'attribut ''virtual''. 
  
-<code cpp> 
-#include <iostream> 
- 
-class A 
-{ 
- public: 
-  virtual void f() { std::cout << "A" << std::endl;} 
-}; 
- 
-class B : public A 
-{ 
- public: 
-  void f() { std::cout << "B" << std::endl;} 
-}; 
- 
-int main() 
-{ 
-  B b; 
-  A *a = &b; 
-  // Sans virtual, on affiche "A". 
-  // Avec virtual, on affiche "B". 
-  a->f(); 
-  b.f(); 
-} 
-</code> 
- 
-====overload==== 
-  * Cas général 
-Deux méthodes ont le même nom mais avec des arguments de type différent. 
- 
-<code cpp> 
-#include <iostream> 
- 
-void f() { std::cout << "void" << std::endl;} 
-void f(int) { std::cout << "int" << std::endl;} 
- 
-int main() 
-{ 
-  f(); 
-  f(1); 
-} 
-</code> 
- 
-Attention, il n'est pas possible d'avoir deux méthodes avec pour seule différence le type de retour (prototype identique). 
- 
-<code cpp> 
-// Ambigu et interdit 
-void f() { std::cout << "void" << std::endl;} 
-int f() { std::cout << "int" << std::endl;} 
-</code> 
- 
-  * Cas de deux méthodes ayant le même prototype. 
-<code cpp> 
-void fn(int i, int j); 
-void fn(int i, int ...); 
-</code> 
-Dans le cas de l'appel à la fonction ''fn(1, 2)'', la fonction ayant le prototype exact sera appelée (soit ''void fn(int i, int j)''). 
- 
-  * Héritage 
-Le compilateur ne sait pas gérer la surcharge à travers l'héritage. 
-<code cpp> 
-#include <iostream> 
-#include <string> 
- 
-struct BaseInt 
-{ 
-  void Func(int) { std::cout << "BaseInt...\n"; } 
-  void Func(double) { std::cout << "BaseDouble...\n"; } 
-}; 
- 
-struct BaseString 
-{ 
-  void Func(std::string) { std::cout << "BaseString...\n"; } 
-}; 
- 
-struct Derived : public BaseInt, public BaseString 
-{ 
-}; 
- 
-int main() 
-{ 
-  Derived d; 
-  d.Func(10.); 
-} 
-</code> 
- 
-Cela donne le message d'erreur : 
- 
-  main.cpp:21:5: error: request for member ‘Func’ is ambiguous 
- 
-Il est nécessaire d'ajouter explicitement les méthodes via ''using''. 
- 
-<code cpp> 
-struct Derived : public BaseInt, public BaseString 
-{ 
-  using BaseInt::Func; 
-  using BaseString::Func; 
-}; 
-</code> 
-====Méthodes statiques dans une interface==== 
-Normalement, c'est interdit mais apparemment, c'est possible en faisant du bricolage. 
- 
-[[http://www.cheshirekow.com/wordpress/?p=55|Static Interfaces in C++]] {{ :lang:cpp:heritage:static_interfaces_in_c_brain_dump_2019-12-19_2_21_38_pm_.html |Archive du 13/08/2019 le 19/12/2019}} 
- 
-L'interface : 
-<code cpp> 
-template < typename T > 
-class StaticInterface 
-{ 
-  public: 
-    StaticInterface() 
-    { 
-      int(*fooCheck)(int)   = T::foo; 
-      bool(*barCheck)(bool) = T::bar; 
-    } 
-}; 
-</code> 
- 
-Une implémentation de la classe : 
-<code cpp> 
-class DerivedClass : public StaticInterface<DerivedClass> 
-{ 
-  public: 
-    static int foo(int  param){ return 10; } 
-    static bool bar(bool param){ return 20; } 
-}; 
-</code> 
- 
- 
-====reinterpret_cast sur une classe avec héritage==== 
-Un ''static_cast'' ou un ''dynamic_cast'' ne pose pas de problème dans le cas d'héritage multiple. 
- 
-Par contre, un ''reinterpret_cast'' d'un ''void *'' doit toujours se faire sur la classe la plus basse (la plus enfant). Un ''void *'' ne possède aucune information du type de la classe et donc le compilateur ne sait pas comment s'en sortir. Par exemple avec les méthodes virtuelles, il ne peut pas savoir à quelle classe appartient la première méthode en tête de la ''vtable''. Il y a les mêmes problèmes avec les attributs de la classe. 
- 
-[[https://stackoverflow.com/questions/2379427/multiple-inheritance-unexpected-result-after-cast-from-void-to-2nd-base-class|multiple inheritance: unexpected result after cast from void * to 2nd base class]] {{ :lang:cpp:heritage:c_-_multiple_inheritance_unexpected_result_after_cast_from_void_to_2nd_base_class_-_stack_overflow_2019-12-19_2_21_51_pm_.html |Archive du 04/03/2010 le 19/12/2019}} 
- 
-====Définir une méthode purement virtuelle d'un parent par un autre parent==== 
-Il est important que ''Base'' ne contienne que les méthodes virtuelles car les deux classes ''Mixin'' et ''Example'' vont en hériter. 
- 
-Si ''Base::test'' n'est pas purement virtuelle, ça sera toujours la méthode de la classe ''Mixin'' qui sera appelée. 
- 
-<code cpp> 
-class Base { 
-public: 
-    virtual void test() = 0; 
-}; 
- 
-template <typename T> 
-class Mixin : virtual T { 
-public: 
-    virtual void test() override { /*... do stuff ... */ } 
-}; 
- 
-class Example : public virtual Base, public virtual Mixin<Base> { 
-    /* definitions specific to the Example class _not_including_ 
-       a definition of the test() method */ 
-}; 
-</code> 
- 
-{{ :lang:cpp:heritage:class_example_inherit_graph.svg |}} 
- 
-[[https://stackoverflow.com/questions/19528338/how-to-override-a-function-in-another-base-class|How to override a function in another base class?]] {{ :lang:cpp:heritage:c_-_how_to_override_a_function_in_another_base_class_-_stack_overflow_2019-12-19_2_22_01_pm_.html |Archive du 22/10/2013 le 19/12/2019}} 
- 
-====Forcer un template à hériter d'une classe==== 
-<code cpp> 
-template <class M> 
-class InterfaceVisitable { 
-  static_assert(std::is_base_of<XXXXXXXX, M>::value, 
-                "M must be a descendant of XXXXXXXX"); 
-}; 
-</code> 
- 
-====Caster T<Base>* t = new T<Derive>()==== 
-C'est impossible. La notion d'héritage ne marche que pour la classe, pas pour les arguments du template. 
- 
-L'exemple ci-dessous ne marche pas. Caster l'un en l'autre poserait des problèmes pour l'accès à la variable a. 
- 
-<code cpp> 
-#include <cstddef> 
-#include <iostream> 
- 
-class A 
-{ 
- public: 
-  int a; 
-}; 
- 
-class B : public A 
-{ 
- public: 
-  int b; 
-}; 
- 
-template<typename T> 
-class C 
-{ 
- public: 
-  T t[2]; 
-}; 
- 
-int main() 
-{ 
-  C<A> a; 
-  C<B> b; 
- 
-  std::cout << (((size_t)(&a.t[1])) - ((size_t)(&a.t[0]))) << std::endl; 
-  std::cout << (((size_t)(&b.t[1])) - ((size_t)(&b.t[0]))) << std::endl; 
- 
-  return 0; 
-} 
-</code> 
- 
-Rendu : 
-<code> 
-4 
-8 
-</code> 
lang/cpp/heritage.1583304781.txt.gz · Dernière modification : 2020/03/04 07:53 de root