Ceci est une ancienne révision du document !
Table des matières
override
Une classe enfant redéfinit une méthode du parent. Cela peut se faire avec ou sans l'attribut virtual
.
#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(); }
overload
Deux méthodes ont le même nom mais avec des arguments de type différent.
#include <iostream> void f() { std::cout << "void" << std::endl;} void f(int) { std::cout << "int" << std::endl;} int main() { f(); f(1); }
Attention, il n'est pas possible d'avoir deux méthodes avec pour seule différence le type de retour (prototype identique).
// Ambigu et interdit void f() { std::cout << "void" << std::endl;} int f() { std::cout << "int" << std::endl;}
Cas de deux méthodes ayant le même prototype.
void fn(int i, int j); void fn(int i, int ...);
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)
).
Méthodes statiques dans une interface
Normalement, c'est interdit mais apparemment, c'est possible en faisant du bricolage.
Static Interfaces in C++ Archive du 13/08/2019 le 19/12/2019
L'interface :
template < typename T > class StaticInterface { public: StaticInterface() { int(*fooCheck)(int) = T::foo; bool(*barCheck)(bool) = T::bar; } };
Une implémentation de la classe :
class DerivedClass : public StaticInterface<DerivedClass> { public: static int foo(int param){ return 10; } static bool bar(bool param){ return 20; } };
Cast vers un parent d'un héritage multiple
Depuis Parent1
, caster this
vers Parent2
.
Il ne faut surtout pas faire (ci-dessous). Sinon, les méthodes virtuelles (au minimum) appelleront n'importe quoi. De toute façon d'une manière générale, reinterpret_cast
ne s'utilise que vers la classe la plus basse dans l'héritage.
Parent2* p = reinterpret_cast<Parent2*>(this);
Il faut faire (ci-dessous). Puis un cast
naturel se fera de Enfant
vers Parent2
.
Parent2* p = static_cast<Enfant*>(this);
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.
multiple inheritance: unexpected result after cast from void * to 2nd base class 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.
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 */ };
How to override a function in another base class? Archive du 22/10/2013 le 19/12/2019
Forcer un template à hériter d'une classe
template <class M> class InterfaceVisitable { static_assert(std::is_base_of<XXXXXXXX, M>::value, "M must be a descendant of XXXXXXXX"); };
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.
#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; }
Rendu :
4 8