Outils pour utilisateurs

Outils du site


lang:cpp:heritage

Ceci est une ancienne révision du document !


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

  • Cas général

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)).

  • Héritage

Le compilateur ne sait pas gérer la surcharge à travers l'héritage.

#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.);
}

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.

struct Derived : public BaseInt, public BaseString
{
  using BaseInt::Func;
  using BaseString::Func;
};

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; }
};

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
lang/cpp/heritage.1583304998.txt.gz · Dernière modification : 2020/03/04 07:56 de root